Last active
June 6, 2021 07:03
-
-
Save qwe321qwe321qwe321/6bf01b73dc6e9752ba8f00f24cdc741d to your computer and use it in GitHub Desktop.
Test Unity Burst Compiler performance in different scenarios. (Burst: 1.5.3, Unity: 2019.4.17f1)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Unity.Burst; | |
using Unity.Collections; | |
using Unity.Jobs; | |
using Unity.Mathematics; | |
using MathRandom = Unity.Mathematics.Random; | |
using UnityEngine; | |
using System; | |
using System.Runtime.InteropServices; | |
using UnityEngine.Profiling; | |
namespace PeDev { | |
public class BurstCompileTest : MonoBehaviour { | |
public int count = 1000000; | |
public void OnGUI() { | |
if (GUILayout.Button("Test1")) { | |
Profiler.BeginSample("TestPerformance1: Different ways to set values"); | |
TestPerformance1.Execute(count); | |
Profiler.EndSample(); | |
} | |
if (GUILayout.Button("Test2+3+4")) { | |
Profiler.BeginSample("TestPerformance2: math+float432 computation"); | |
TestPerformance2.Execute(count); | |
Profiler.EndSample(); | |
Profiler.BeginSample("TestPerformance3: Mathf+Vector432 computation"); | |
TestPerformance3.Execute(count); | |
Profiler.EndSample(); | |
Profiler.BeginSample("TestPerformance4: Does burst compile external static method?"); | |
TestPerformance4.Execute(count); | |
Profiler.EndSample(); | |
} | |
if (GUILayout.Button("Test5")) { | |
Profiler.BeginSample("TestPerformance5: Vector2 vs float2"); | |
TestPerformance5.Execute(count); | |
Profiler.EndSample(); | |
} | |
if (GUILayout.Button("Test6")) { | |
Profiler.BeginSample("TestPerformance6: Does [ReadOnly]/[WriteOnly] matter?"); | |
TestPerformance6.Execute(count); | |
Profiler.EndSample(); | |
} | |
} | |
private static class TestPerformance1 { | |
public static void Execute(int count) { | |
NativeArray<MyStruct> myStructs = new NativeArray<MyStruct>(count, Allocator.TempJob); | |
NativeArray<MyStruct> randomValues = new NativeArray<MyStruct>(count, Allocator.TempJob); | |
JobHandle handle; | |
Randomize(randomValues, count); | |
Profiler.BeginSample("Set Values"); | |
for (int i = 0; i < myStructs.Length; i++) { | |
MyStruct.SetValue(ref myStructs.GetRef(i), randomValues[i]); | |
} | |
Profiler.EndSample(); | |
Randomize(randomValues, count); | |
Profiler.BeginSample("Set Values by Job"); | |
handle = new SetValueJob() { | |
array = myStructs, | |
values = randomValues | |
}.Schedule(); | |
handle.Complete(); | |
Profiler.EndSample(); | |
Randomize(randomValues, count); | |
Profiler.BeginSample("Set Values by FunctionPointer.Invoke"); | |
unsafe { | |
var setValue = BurstCompiler.CompileFunctionPointer((MyStruct.SetValueDelegate)MyStruct.SetValue).Invoke; | |
for (int i = 0; i < count; i++) { | |
setValue.Invoke((MyStruct*)myStructs.GetPointer(i), (MyStruct*)randomValues.GetPointer(i)); | |
} | |
} | |
Profiler.EndSample(); | |
Randomize(randomValues, count); | |
Profiler.BeginSample("Set Values by FunctionPointer+Job"); | |
unsafe { | |
var setValue = BurstCompiler.CompileFunctionPointer((MyStruct.SetValueDelegate)MyStruct.SetValue); | |
new SetValueFunctionPtrJob() { | |
array = myStructs, | |
values = randomValues, | |
setValue = setValue | |
}.Run(); | |
} | |
Profiler.EndSample(); | |
Randomize(randomValues, count); | |
Profiler.BeginSample("Set Values by Job.Run()"); | |
new SetValueJob() { | |
array = myStructs, | |
values = randomValues | |
}.Run(); | |
Profiler.EndSample(); | |
Randomize(randomValues, count); | |
Profiler.BeginSample("Set Values by Job.Execute()"); | |
new SetValueJob() { | |
array = myStructs, | |
values = randomValues | |
}.Execute(); | |
Profiler.EndSample(); | |
myStructs.Dispose(); | |
randomValues.Dispose(); | |
} | |
private static void Randomize(NativeArray<MyStruct> values, int count) { | |
JobHandle handle = new RandomJob() { | |
array = values, | |
seedBase = (uint)UnityEngine.Random.Range(0, int.MaxValue), | |
}.Schedule(count, 64); | |
handle.Complete(); | |
} | |
[BurstCompile] | |
struct RandomJob : IJobParallelFor { | |
public NativeArray<MyStruct> array; | |
public uint seedBase; | |
public void Execute(int index) { | |
array[index] = MyStruct.Random(seedBase + (uint)index); | |
} | |
} | |
[BurstCompile] | |
struct SetValueJob : IJob { | |
public NativeArray<MyStruct> array; | |
public NativeArray<MyStruct> values; | |
public void Execute() { | |
int count = array.Length; | |
for (int i = 0; i < count; i++) { | |
MyStruct.SetValue(ref array.GetRef(i), values[i]); | |
} | |
} | |
} | |
[BurstCompile] | |
struct SetValueFunctionPtrJob : IJob { | |
public NativeArray<MyStruct> array; | |
public NativeArray<MyStruct> values; | |
public FunctionPointer<MyStruct.SetValueDelegate> setValue; | |
public unsafe void Execute() { | |
int count = array.Length; | |
for (int i = 0; i < count; i++) { | |
setValue.Invoke((MyStruct*)array.GetPointer(i), (MyStruct*)values.GetPointer(i)); | |
} | |
} | |
} | |
[BurstCompile] | |
struct MyStruct { | |
public float4 f4; | |
public float3 f3; | |
public float2 f2; | |
public float f1; | |
public bool b1; | |
public static void SetValue(ref MyStruct myStruct, MyStruct value) { | |
myStruct.f4 = value.f4; | |
myStruct.f3 = value.f3; | |
myStruct.f2 = value.f2; | |
myStruct.f1 = value.f1; | |
myStruct.b1 = value.b1; | |
} | |
public static void SetValue(ref MyStruct myStruct, float4 f4, float3 f3, float2 f2, float f1, bool b1) { | |
myStruct.f4 = f4; | |
myStruct.f3 = f3; | |
myStruct.f2 = f2; | |
myStruct.f1 = f1; | |
myStruct.b1 = b1; | |
} | |
public unsafe delegate void SetValueDelegate(MyStruct* myStruct, MyStruct* value); | |
[BurstCompile] | |
public unsafe static void SetValue(MyStruct* myStruct, MyStruct* value) { | |
myStruct->f4 = value->f4; | |
myStruct->f3 = value->f3; | |
myStruct->f2 = value->f2; | |
myStruct->f1 = value->f1; | |
myStruct->b1 = value->b1; | |
} | |
public static MyStruct Random(uint seed) { | |
MathRandom random = new MathRandom(seed); | |
return new MyStruct() { | |
f4 = random.NextFloat4(), | |
f3 = random.NextFloat3(), | |
f2 = random.NextFloat2(), | |
f1 = random.NextFloat(), | |
b1 = random.NextBool(), | |
}; | |
} | |
} | |
} | |
private static class TestPerformance2 { | |
public static void Execute(int count) { | |
NativeArray<MyStruct> myStructs = new NativeArray<MyStruct>(count, Allocator.TempJob); | |
NativeArray<MyStruct> randomValues = new NativeArray<MyStruct>(count, Allocator.TempJob); | |
Randomize(randomValues, count); | |
Profiler.BeginSample("AssignJob.Run()"); | |
new AssignJob() { | |
array = myStructs, | |
values = randomValues | |
}.Run(); | |
Profiler.EndSample(); | |
Randomize(randomValues, count); | |
Profiler.BeginSample("SetValuesJob.Run()"); | |
new SetValuesJob() { | |
array = myStructs, | |
values = randomValues | |
}.Run(); | |
Profiler.EndSample(); | |
Randomize(randomValues, count); | |
Profiler.BeginSample("DotJob.Run()"); | |
new DotJob() { | |
array = myStructs, | |
values = randomValues | |
}.Run(); | |
Profiler.EndSample(); | |
Profiler.BeginSample("LengthJob.Run()"); | |
new LengthJob() { | |
array = myStructs, | |
}.Run(); | |
Profiler.EndSample(); | |
Profiler.BeginSample("NormalizeJob.Run()"); | |
new NormalizeJob() { | |
array = myStructs, | |
}.Run(); | |
Profiler.EndSample(); | |
myStructs.Dispose(); | |
randomValues.Dispose(); | |
} | |
private static void Randomize(NativeArray<MyStruct> values, int count) { | |
JobHandle handle = new RandomJob() { | |
array = values, | |
seedBase = (uint)UnityEngine.Random.Range(0, int.MaxValue), | |
}.Schedule(count, 64); | |
handle.Complete(); | |
} | |
[BurstCompile] | |
struct RandomJob : IJobParallelFor { | |
public NativeArray<MyStruct> array; | |
public uint seedBase; | |
public void Execute(int index) { | |
array.GetRef(index) = MyStruct.Random(seedBase + (uint)index); | |
} | |
} | |
[BurstCompile] | |
struct AssignJob : IJob { | |
public NativeArray<MyStruct> array; | |
public NativeArray<MyStruct> values; | |
public void Execute() { | |
int count = array.Length; | |
for (int i = 0; i < count; i++) { | |
array[i] = values[i]; | |
} | |
} | |
} | |
[BurstCompile] | |
struct SetValuesJob : IJob { | |
public NativeArray<MyStruct> array; | |
public NativeArray<MyStruct> values; | |
public void Execute() { | |
int count = array.Length; | |
for (int i = 0; i < count; i++) { | |
MyStruct.SetValues(ref array.GetRef(i), values[i]); | |
} | |
} | |
} | |
[BurstCompile] | |
struct DotJob : IJob { | |
public NativeArray<MyStruct> array; | |
public NativeArray<MyStruct> values; | |
public void Execute() { | |
int count = array.Length; | |
for (int i = 0; i < count; i++) { | |
MyStruct.Dot(ref array.GetRef(i), values[i]); | |
} | |
} | |
} | |
[BurstCompile] | |
struct LengthJob : IJob { | |
public NativeArray<MyStruct> array; | |
public void Execute() { | |
int count = array.Length; | |
for (int i = 0; i < count; i++) { | |
MyStruct.Length(ref array.GetRef(i)); | |
} | |
} | |
} | |
[BurstCompile] | |
struct NormalizeJob : IJob { | |
public NativeArray<MyStruct> array; | |
public void Execute() { | |
int count = array.Length; | |
for (int i = 0; i < count; i++) { | |
MyStruct.Normalize(ref array.GetRef(i)); | |
} | |
} | |
} | |
struct MyStruct { | |
public float4 f4; | |
public float3 f3; | |
public float2 f2; | |
public float result; | |
public static void SetValues(ref MyStruct myStruct, MyStruct value) { | |
myStruct.f4 = value.f4; | |
myStruct.f3 = value.f3; | |
myStruct.f2 = value.f2; | |
} | |
public static void Dot(ref MyStruct myStruct, MyStruct value) { | |
float dot4 = math.dot(myStruct.f4, value.f4); | |
float dot3 = math.dot(myStruct.f3, value.f3); | |
float dot2 = math.dot(myStruct.f2, value.f2); | |
myStruct.result = dot4 + dot3 + dot2; | |
} | |
public static void Length(ref MyStruct myStruct) { | |
float length4 = math.length(myStruct.f4); | |
float length3 = math.length(myStruct.f3); | |
float length2 = math.length(myStruct.f2); | |
myStruct.result = length4 + length3 + length2; | |
} | |
public static void Normalize(ref MyStruct myStruct) { | |
myStruct.f4 = math.normalize(myStruct.f4); | |
myStruct.f3 = math.normalize(myStruct.f3); | |
myStruct.f2 = math.normalize(myStruct.f2); | |
} | |
public static MyStruct Random(uint seed) { | |
MathRandom random = new MathRandom(seed); | |
return new MyStruct() { | |
f4 = random.NextFloat4(), | |
f3 = random.NextFloat3(), | |
f2 = random.NextFloat2() | |
}; | |
} | |
} | |
} | |
private static class TestPerformance3 { | |
public static void Execute(int count) { | |
NativeArray<MyStruct> myStructs = new NativeArray<MyStruct>(count, Allocator.TempJob); | |
NativeArray<MyStruct> randomValues = new NativeArray<MyStruct>(count, Allocator.TempJob); | |
Randomize(randomValues, count); | |
Profiler.BeginSample("AssignJob.Run()"); | |
new AssignJob() { | |
array = myStructs, | |
values = randomValues | |
}.Run(); | |
Profiler.EndSample(); | |
Randomize(randomValues, count); | |
Profiler.BeginSample("SetValuesJob.Run()"); | |
new SetValuesJob() { | |
array = myStructs, | |
values = randomValues | |
}.Run(); | |
Profiler.EndSample(); | |
Randomize(randomValues, count); | |
Profiler.BeginSample("DotJob.Run()"); | |
new DotJob() { | |
array = myStructs, | |
values = randomValues | |
}.Run(); | |
Profiler.EndSample(); | |
Profiler.BeginSample("LengthJob.Run()"); | |
new LengthJob() { | |
array = myStructs, | |
}.Run(); | |
Profiler.EndSample(); | |
Profiler.BeginSample("NormalizeJob.Run()"); | |
new NormalizeJob() { | |
array = myStructs, | |
}.Run(); | |
Profiler.EndSample(); | |
myStructs.Dispose(); | |
randomValues.Dispose(); | |
} | |
private static void Randomize(NativeArray<MyStruct> values, int count) { | |
JobHandle handle = new RandomJob() { | |
array = values, | |
seedBase = (uint)UnityEngine.Random.Range(0, int.MaxValue), | |
}.Schedule(count, 64); | |
handle.Complete(); | |
} | |
[BurstCompile] | |
struct RandomJob : IJobParallelFor { | |
public NativeArray<MyStruct> array; | |
public uint seedBase; | |
public void Execute(int index) { | |
array.GetRef(index) = MyStruct.Random(seedBase + (uint)index); | |
} | |
} | |
[BurstCompile] | |
struct AssignJob : IJob { | |
public NativeArray<MyStruct> array; | |
public NativeArray<MyStruct> values; | |
public void Execute() { | |
int count = array.Length; | |
for (int i = 0; i < count; i++) { | |
array[i] = values[i]; | |
} | |
} | |
} | |
[BurstCompile] | |
struct SetValuesJob : IJob { | |
public NativeArray<MyStruct> array; | |
public NativeArray<MyStruct> values; | |
public void Execute() { | |
int count = array.Length; | |
for (int i = 0; i < count; i++) { | |
MyStruct.SetValues(ref array.GetRef(i), values[i]); | |
} | |
} | |
} | |
[BurstCompile] | |
struct DotJob : IJob { | |
public NativeArray<MyStruct> array; | |
public NativeArray<MyStruct> values; | |
public void Execute() { | |
int count = array.Length; | |
for (int i = 0; i < count; i++) { | |
MyStruct.Dot(ref array.GetRef(i), values[i]); | |
} | |
} | |
} | |
[BurstCompile] | |
struct LengthJob : IJob { | |
public NativeArray<MyStruct> array; | |
public void Execute() { | |
int count = array.Length; | |
for (int i = 0; i < count; i++) { | |
MyStruct.Length(ref array.GetRef(i)); | |
} | |
} | |
} | |
[BurstCompile] | |
struct NormalizeJob : IJob { | |
public NativeArray<MyStruct> array; | |
public void Execute() { | |
int count = array.Length; | |
for (int i = 0; i < count; i++) { | |
MyStruct.Normalize(ref array.GetRef(i)); | |
} | |
} | |
} | |
struct MyStruct { | |
public Vector4 f4; | |
public Vector3 f3; | |
public Vector2 f2; | |
public float result; | |
public static void SetValues(ref MyStruct myStruct, MyStruct value) { | |
myStruct.f4 = value.f4; | |
myStruct.f3 = value.f3; | |
myStruct.f2 = value.f2; | |
} | |
public static void Dot(ref MyStruct myStruct, MyStruct value) { | |
float dot4 = Vector4.Dot(myStruct.f4, value.f4); | |
float dot3 = Vector3.Dot(myStruct.f3, value.f3); | |
float dot2 = Vector2.Dot(myStruct.f2, value.f2); | |
myStruct.result = dot4 + dot3 + dot2; | |
} | |
public static void Length(ref MyStruct myStruct) { | |
float length4 = Vector4.Magnitude(myStruct.f4); | |
float length3 = Vector3.Magnitude(myStruct.f3); | |
float length2 = myStruct.f2.magnitude; | |
myStruct.result = length4 + length3 + length2; | |
} | |
public static void Normalize(ref MyStruct myStruct) { | |
myStruct.f4 = Vector4.Normalize(myStruct.f4); | |
myStruct.f3 = Vector3.Normalize(myStruct.f3); | |
myStruct.f2 = myStruct.f2.normalized; | |
} | |
public static MyStruct Random(uint seed) { | |
MathRandom random = new MathRandom(seed); | |
return new MyStruct() { | |
f4 = random.NextFloat4(), | |
f3 = random.NextFloat3(), | |
f2 = random.NextFloat2() | |
}; | |
} | |
} | |
} | |
private static class TestPerformance4 { | |
public static void Execute(int count) { | |
NativeArray<MyStruct> myStructs = new NativeArray<MyStruct>(count, Allocator.TempJob); | |
NativeArray<MyStruct> randomValues = new NativeArray<MyStruct>(count, Allocator.TempJob); | |
Randomize(randomValues, count); | |
Profiler.BeginSample("AssignJob.Run()"); | |
new AssignJob() { | |
array = myStructs, | |
values = randomValues | |
}.Run(); | |
Profiler.EndSample(); | |
Randomize(randomValues, count); | |
Profiler.BeginSample("SetValuesJob.Run()"); | |
new SetValuesJob() { | |
array = myStructs, | |
values = randomValues | |
}.Run(); | |
Profiler.EndSample(); | |
Randomize(randomValues, count); | |
Profiler.BeginSample("DotJob.Run()"); | |
new DotJob() { | |
array = myStructs, | |
values = randomValues | |
}.Run(); | |
Profiler.EndSample(); | |
Profiler.BeginSample("LengthJob.Run()"); | |
new LengthJob() { | |
array = myStructs, | |
}.Run(); | |
Profiler.EndSample(); | |
Profiler.BeginSample("NormalizeJob.Run()"); | |
new NormalizeJob() { | |
array = myStructs, | |
}.Run(); | |
Profiler.EndSample(); | |
myStructs.Dispose(); | |
randomValues.Dispose(); | |
} | |
private static void Randomize(NativeArray<MyStruct> values, int count) { | |
JobHandle handle = new RandomJob() { | |
array = values, | |
seedBase = (uint)UnityEngine.Random.Range(0, int.MaxValue), | |
}.Schedule(count, 64); | |
handle.Complete(); | |
} | |
[BurstCompile] | |
struct RandomJob : IJobParallelFor { | |
public NativeArray<MyStruct> array; | |
public uint seedBase; | |
public void Execute(int index) { | |
array.GetRef(index) = MyStruct.Random(seedBase + (uint)index); | |
} | |
} | |
[BurstCompile] | |
struct AssignJob : IJob { | |
public NativeArray<MyStruct> array; | |
public NativeArray<MyStruct> values; | |
public void Execute() { | |
int count = array.Length; | |
for (int i = 0; i < count; i++) { | |
array[i] = values[i]; | |
} | |
} | |
} | |
[BurstCompile] | |
struct SetValuesJob : IJob { | |
public NativeArray<MyStruct> array; | |
public NativeArray<MyStruct> values; | |
public void Execute() { | |
int count = array.Length; | |
for (int i = 0; i < count; i++) { | |
ref var myStruct = ref array.GetRef(i); | |
var value = values[i]; | |
myStruct.f4 = value.f4; | |
myStruct.f3 = value.f3; | |
myStruct.f2 = value.f2; | |
} | |
} | |
} | |
[BurstCompile] | |
struct DotJob : IJob { | |
public NativeArray<MyStruct> array; | |
public NativeArray<MyStruct> values; | |
public void Execute() { | |
int count = array.Length; | |
for (int i = 0; i < count; i++) { | |
ref var myStruct = ref array.GetRef(i); | |
var value = values[i]; | |
float dot4 = math.dot(myStruct.f4, value.f4); | |
float dot3 = math.dot(myStruct.f3, value.f3); | |
float dot2 = math.dot(myStruct.f2, value.f2); | |
myStruct.result = dot4 + dot3 + dot2; | |
} | |
} | |
} | |
[BurstCompile] | |
struct LengthJob : IJob { | |
public NativeArray<MyStruct> array; | |
public void Execute() { | |
int count = array.Length; | |
for (int i = 0; i < count; i++) { | |
ref var myStruct = ref array.GetRef(i); | |
float length4 = math.length(myStruct.f4); | |
float length3 = math.length(myStruct.f3); | |
float length2 = math.length(myStruct.f2); | |
myStruct.result = length4 + length3 + length2; | |
} | |
} | |
} | |
[BurstCompile] | |
struct NormalizeJob : IJob { | |
public NativeArray<MyStruct> array; | |
public void Execute() { | |
int count = array.Length; | |
for (int i = 0; i < count; i++) { | |
ref var myStruct = ref array.GetRef(i); | |
myStruct.f4 = math.normalize(myStruct.f4); | |
myStruct.f3 = math.normalize(myStruct.f3); | |
myStruct.f2 = math.normalize(myStruct.f2); | |
} | |
} | |
} | |
struct MyStruct { | |
public float4 f4; | |
public float3 f3; | |
public float2 f2; | |
public float result; | |
public static MyStruct Random(uint seed) { | |
MathRandom random = new MathRandom(seed); | |
return new MyStruct() { | |
f4 = random.NextFloat4(), | |
f3 = random.NextFloat3(), | |
f2 = random.NextFloat2() | |
}; | |
} | |
} | |
} | |
private static class TestPerformance5 { | |
public static void Execute(int count) { | |
NativeArray<Vector2> vector2s = new NativeArray<Vector2>(count, Allocator.TempJob); | |
NativeArray<float2> float2s = new NativeArray<float2>(count, Allocator.TempJob); | |
NativeArray<Vector2> randomValues = new NativeArray<Vector2>(count, Allocator.TempJob); | |
NativeArray<float> result = new NativeArray<float>(count, Allocator.TempJob); | |
Randomize(randomValues, count); | |
Profiler.BeginSample("AssignTofloat2Job"); | |
new AssignTofloat2Job() { | |
array = float2s, | |
values = randomValues | |
}.Run(); | |
Profiler.EndSample(); | |
Profiler.BeginSample("AssignToVector2Job"); | |
new AssignToVector2Job() { | |
array = vector2s, | |
values = randomValues | |
}.Run(); | |
Profiler.EndSample(); | |
Profiler.BeginSample("Dotfloat2Job"); | |
new Dotfloat2Job() { | |
array = float2s, | |
result = result | |
}.Run(); | |
Profiler.EndSample(); | |
Profiler.BeginSample("DotVector2Job"); | |
new DotVector2Job() { | |
array = vector2s, | |
result = result | |
}.Run(); | |
Profiler.EndSample(); | |
Profiler.BeginSample("Lengthfloat2Job"); | |
new Lengthfloat2Job() { | |
array = float2s, | |
result = result | |
}.Run(); | |
Profiler.EndSample(); | |
Profiler.BeginSample("LengthVector2Job"); | |
new LengthVector2Job() { | |
array = vector2s, | |
result = result | |
}.Run(); | |
Profiler.EndSample(); | |
Profiler.BeginSample("Normalizefloat2Job"); | |
new Normalizefloat2Job() { | |
array = float2s, | |
}.Run(); | |
Profiler.EndSample(); | |
Profiler.BeginSample("NormalizeVecotr2ByFloat2Job"); | |
new NormalizeVecotr2ByFloat2Job() { | |
array = vector2s, | |
}.Run(); | |
Profiler.EndSample(); | |
Profiler.BeginSample("AssignToVector2Job Execute"); | |
new AssignToVector2Job() { | |
array = vector2s, | |
values = randomValues | |
}.Execute(); | |
Profiler.EndSample(); | |
Profiler.BeginSample("NormalizeVector2Job"); | |
new NormalizeVector2Job() { | |
array = vector2s, | |
}.Run(); | |
Profiler.EndSample(); | |
Profiler.BeginSample("AssignTofloat2Job Execute"); | |
new AssignTofloat2Job() { | |
array = float2s, | |
values = randomValues | |
}.Execute(); | |
Profiler.EndSample(); | |
vector2s.Dispose(); | |
float2s.Dispose(); | |
randomValues.Dispose(); | |
result.Dispose(); | |
} | |
private static void Randomize(NativeArray<Vector2> values, int count) { | |
JobHandle handle = new RandomJob() { | |
array = values, | |
seedBase = (uint)UnityEngine.Random.Range(0, int.MaxValue), | |
}.Schedule(count, 64); | |
handle.Complete(); | |
} | |
[BurstCompile] | |
struct RandomJob : IJobParallelFor { | |
public NativeArray<Vector2> array; | |
public uint seedBase; | |
public void Execute(int index) { | |
MathRandom random = new MathRandom(seedBase + (uint)index); | |
array.GetRef(index) = random.NextFloat2(); | |
} | |
} | |
[BurstCompile] | |
struct AssignToVector2Job : IJob { | |
public NativeArray<Vector2> array; | |
public NativeArray<Vector2> values; | |
public void Execute() { | |
int count = array.Length; | |
for (int i = 0; i < count; i++) { | |
array[i] = values[i]; | |
} | |
} | |
} | |
[BurstCompile] | |
struct AssignTofloat2Job : IJob { | |
public NativeArray<float2> array; | |
public NativeArray<Vector2> values; | |
public void Execute() { | |
int count = array.Length; | |
for (int i = 0; i < count; i++) { | |
array[i] = values[i]; | |
} | |
} | |
} | |
[BurstCompile] | |
struct LengthVector2Job : IJob { | |
public NativeArray<Vector2> array; | |
public NativeArray<float> result; | |
public void Execute() { | |
int count = array.Length; | |
for (int i = 0; i < count; i++) { | |
result[i] = array[i].magnitude; | |
} | |
} | |
} | |
[BurstCompile] | |
struct DotVector2Job : IJob { | |
public NativeArray<Vector2> array; | |
public NativeArray<float> result; | |
public void Execute() { | |
int count = array.Length; | |
for (int i = 0; i < count; i++) { | |
result[i] = Vector2.Dot(array[i], array[i]); | |
} | |
} | |
} | |
[BurstCompile] | |
struct Dotfloat2Job : IJob { | |
public NativeArray<float2> array; | |
public NativeArray<float> result; | |
public void Execute() { | |
int count = array.Length; | |
for (int i = 0; i < count; i++) { | |
result[i] = math.dot(array[i], array[i]); | |
} | |
} | |
} | |
[BurstCompile] | |
struct Lengthfloat2Job : IJob { | |
public NativeArray<float2> array; | |
public NativeArray<float> result; | |
public void Execute() { | |
int count = array.Length; | |
for (int i = 0; i < count; i++) { | |
result[i] = math.length(array[i]); | |
} | |
} | |
} | |
[BurstCompile] | |
struct NormalizeVector2Job : IJob { | |
public NativeArray<Vector2> array; | |
public void Execute() { | |
int count = array.Length; | |
for (int i = 0; i < count; i++) { | |
array[i] = array[i].normalized; | |
} | |
} | |
} | |
[BurstCompile] | |
struct NormalizeVecotr2ByFloat2Job : IJob { | |
public NativeArray<Vector2> array; | |
public void Execute() { | |
int count = array.Length; | |
for (int i = 0; i < count; i++) { | |
ref float2 value = ref UnsafeEx.Reinterpret<Vector2, float2>(ref array.GetRef(i)); | |
value = math.normalize(value); | |
} | |
} | |
} | |
[BurstCompile] | |
struct Normalizefloat2Job : IJob { | |
public NativeArray<float2> array; | |
public void Execute() { | |
int count = array.Length; | |
for (int i = 0; i < count; i++) { | |
array[i] = math.normalize(array[i]); | |
} | |
} | |
} | |
} | |
private static class TestPerformance6 { | |
public static void Execute(int count) { | |
NativeArray<float4> float4s = new NativeArray<float4>(count, Allocator.TempJob); | |
NativeArray<float4> randomValues = new NativeArray<float4>(count, Allocator.TempJob); | |
Randomize(randomValues, count); | |
Clear(float4s, count); | |
Profiler.BeginSample(nameof(AssignWithReadWriteOnlyJob)); | |
new AssignWithReadWriteOnlyJob() { | |
array = float4s, | |
values = randomValues | |
}.Run(); | |
Profiler.EndSample(); | |
Clear(float4s, count); | |
Profiler.BeginSample(nameof(AssignWithReadOnlyJob)); | |
new AssignWithReadOnlyJob() { | |
array = float4s, | |
values = randomValues | |
}.Run(); | |
Profiler.EndSample(); | |
Clear(float4s, count); | |
Profiler.BeginSample(nameof(AssignWithWriteOnlyJob)); | |
new AssignWithWriteOnlyJob() { | |
array = float4s, | |
values = randomValues | |
}.Run(); | |
Profiler.EndSample(); | |
Clear(float4s, count); | |
Profiler.BeginSample(nameof(AssignWithNothingJob)); | |
new AssignWithNothingJob() { | |
array = float4s, | |
values = randomValues | |
}.Run(); | |
Profiler.EndSample(); | |
float4s.Dispose(); | |
randomValues.Dispose(); | |
} | |
private static void Clear(NativeArray<float4> values, int count) { | |
JobHandle handle = new ClearJob() { | |
array = values, | |
}.Schedule(count, 64); | |
handle.Complete(); | |
} | |
private static void Randomize(NativeArray<float4> values, int count) { | |
JobHandle handle = new RandomJob() { | |
array = values, | |
seedBase = (uint)UnityEngine.Random.Range(0, int.MaxValue), | |
}.Schedule(count, 64); | |
handle.Complete(); | |
} | |
[BurstCompile] | |
struct RandomJob : IJobParallelFor { | |
public NativeArray<float4> array; | |
public uint seedBase; | |
public void Execute(int index) { | |
MathRandom random = new MathRandom(seedBase + (uint)index); | |
array.GetRef(index) = random.NextFloat4(); | |
} | |
} | |
[BurstCompile] | |
struct ClearJob : IJobParallelFor { | |
public NativeArray<float4> array; | |
public void Execute(int index) { | |
array[index] = float4.zero; | |
} | |
} | |
[BurstCompile] | |
struct AssignWithNothingJob : IJob { | |
public NativeArray<float4> array; | |
public NativeArray<float4> values; | |
public void Execute() { | |
int count = array.Length; | |
for (int i = 0; i < count; i++) { | |
array[i] = values[i]; | |
} | |
} | |
} | |
[BurstCompile] | |
struct AssignWithReadOnlyJob : IJob { | |
public NativeArray<float4> array; | |
[ReadOnly] | |
public NativeArray<float4> values; | |
public void Execute() { | |
int count = array.Length; | |
for (int i = 0; i < count; i++) { | |
array[i] = values[i]; | |
} | |
} | |
} | |
[BurstCompile] | |
struct AssignWithWriteOnlyJob : IJob { | |
[WriteOnly] | |
public NativeArray<float4> array; | |
public NativeArray<float4> values; | |
public void Execute() { | |
int count = array.Length; | |
for (int i = 0; i < count; i++) { | |
array[i] = values[i]; | |
} | |
} | |
} | |
[BurstCompile] | |
struct AssignWithReadWriteOnlyJob : IJob { | |
[WriteOnly] | |
public NativeArray<float4> array; | |
[ReadOnly] | |
public NativeArray<float4> values; | |
public void Execute() { | |
int count = array.Length; | |
for (int i = 0; i < count; i++) { | |
array[i] = values[i]; | |
} | |
} | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Runtime.InteropServices; | |
using Unity.Collections; | |
using Unity.Collections.LowLevel.Unsafe; | |
using UnityEngine; | |
namespace PeDev { | |
public static class NativeArrayExtensions { | |
public static ref T GetRef<T>(this NativeArray<T> array, int index) | |
where T : struct { | |
// You might want to validate the index first, as the unsafe method won't do that. | |
if (index < 0 || index >= array.Length) { | |
throw new ArgumentOutOfRangeException(nameof(index)); | |
} | |
unsafe { | |
return ref UnsafeUtilityEx.ArrayElementAsRef<T>(array.GetUnsafePtr(), index); | |
} | |
} | |
public unsafe static void* GetPointer<T>(this NativeArray<T> array, int index) | |
where T : struct { | |
// You might want to validate the index first, as the unsafe method won't do that. | |
if (index < 0 || index >= array.Length) | |
throw new ArgumentOutOfRangeException(nameof(index)); | |
return (byte*)array.GetUnsafePtr() + index * UnsafeUtility.SizeOf<T>(); | |
} | |
public static void CopyTo<T>(this NativeArray<T> array, T[] dst, int length) | |
where T : struct { | |
NativeArray<T>.Copy(array, dst, length); | |
} | |
} | |
public static class UnsafeEx { | |
/// <summary> | |
/// Cast a type to another type in memory level (pointer casting) | |
/// </summary> | |
public static ref TDst Reinterpret<TSrc, TDst>(ref TSrc value) | |
where TSrc : unmanaged | |
where TDst : unmanaged { | |
if (UnsafeUtility.SizeOf<TSrc>() != UnsafeUtility.SizeOf<TDst>()) { | |
throw new InvalidOperationException($"Types {typeof(TSrc)} and {typeof(TDst)} are different sizes - direct reinterpretation is not possible. If this is what you intended, use Reinterpret(<type size>)"); | |
} | |
unsafe { | |
fixed (TSrc* ptr = &value) { | |
return ref System.Runtime.CompilerServices.Unsafe.AsRef<TDst>(ptr); | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment