initial commit

This commit is contained in:
Jo 2025-01-07 02:06:59 +01:00
parent 6715289efe
commit 788c3389af
37645 changed files with 2526849 additions and 80 deletions

View file

@ -0,0 +1,11 @@
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("Burst.Benchmarks")]
namespace UnityBenchShared
{
internal interface IArgumentProvider
{
object Value { get; }
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b45c1accd4ac367d8bf6578a9f4bfc3b
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,398 @@
using System;
using System.Runtime.CompilerServices;
using Unity.Collections;
using Unity.Jobs;
using Unity.Mathematics;
[assembly: InternalsVisibleTo("Burst.Benchmarks")]
namespace UnityBenchShared
{
// These test cases are from the `doc/perf-notes.md` document
internal static class PerfNotes
{
public static int BenchArraySize = 16 * 1024 * 1024;
}
internal struct PartialWrite : IJob, IDisposable
{
[ReadOnly] public NativeArray<int> a;
public NativeArray<int> b;
public struct Provider : IArgumentProvider
{
public object Value
{
get
{
var length = PerfNotes.BenchArraySize;
var job = new PartialWrite()
{
a = new NativeArray<int>(length, Allocator.Persistent),
b = new NativeArray<int>(length, Allocator.Persistent)
};
var random = new System.Random(0);
for (int i = 0; i < length; i++)
{
job.a[i] = random.Next(200);
job.b[i] = random.Next();
}
return job;
}
}
}
public void Execute()
{
for (int i = 0; i < a.Length; ++i)
{
int av = a[i];
if (av > 100)
{
b[i] = av;
}
}
}
public void Dispose()
{
a.Dispose();
b.Dispose();
}
}
internal struct PartialWriteWorkaround : IJob, IDisposable
{
[ReadOnly] public NativeArray<int> a;
public NativeArray<int> b;
public struct Provider : IArgumentProvider
{
public object Value
{
get
{
var length = PerfNotes.BenchArraySize;
var job = new PartialWriteWorkaround()
{
a = new NativeArray<int>(length, Allocator.Persistent),
b = new NativeArray<int>(length, Allocator.Persistent)
};
var random = new System.Random(0);
for (int i = 0; i < length; i++)
{
job.a[i] = random.Next(200);
job.b[i] = random.Next();
}
return job;
}
}
}
public void Execute()
{
for (int i = 0; i < a.Length; ++i)
{
int av = a[i];
int v = b[i];
if (av > 100)
{
v = av;
}
b[i] = v;
}
}
public void Dispose()
{
a.Dispose();
b.Dispose();
}
}
internal struct IntToFloatPenalty : IJob, IDisposable
{
[ReadOnly] public NativeArray<float> b;
public struct Provider : IArgumentProvider
{
public object Value
{
get
{
var length = PerfNotes.BenchArraySize * 4;
var job = new IntToFloatPenalty()
{
b = new NativeArray<float>(length, Allocator.Persistent)
};
return job;
}
}
}
public void Execute()
{
int k = 100;
for (int i = 0; i < b.Length; ++i)
{
b[i] = k;
++k;
}
}
public void Dispose()
{
b.Dispose();
}
}
internal struct DivisionByScalar : IJob, IDisposable
{
float divisor;
[ReadOnly] public NativeArray<float> a;
public NativeArray<float> b;
public struct Provider : IArgumentProvider
{
public object Value
{
get
{
var length = PerfNotes.BenchArraySize;
var job = new DivisionByScalar()
{
divisor = 13,
a = new NativeArray<float>(length, Allocator.Persistent),
b = new NativeArray<float>(length, Allocator.Persistent)
};
var random = new System.Random(0);
for (int i = 0; i < length; i++)
{
job.a[i] = random.Next();
}
return job;
}
}
}
public void Execute()
{
for (int i = 0; i < a.Length; ++i)
{
b[i] = a[i] / divisor;
}
}
public void Dispose()
{
a.Dispose();
b.Dispose();
}
}
internal struct SquareRoot : IJob, IDisposable
{
[ReadOnly] public NativeArray<float> a;
public NativeArray<float> b;
public struct Provider : IArgumentProvider
{
public object Value
{
get
{
var length = PerfNotes.BenchArraySize;
var job = new SquareRoot()
{
a = new NativeArray<float>(length, Allocator.Persistent),
b = new NativeArray<float>(length, Allocator.Persistent)
};
var random = new System.Random(0);
for (int i = 0; i < length; i++)
{
job.a[i] = random.Next();
}
return job;
}
}
}
public void Execute()
{
for (int i = 0; i < a.Length; ++i)
{
b[i] = math.sqrt(a[i]);
}
}
public void Dispose()
{
a.Dispose();
b.Dispose();
}
}
internal struct SquareRootRecip : IJob, IDisposable
{
[ReadOnly] public NativeArray<float> a;
public NativeArray<float> b;
public struct Provider : IArgumentProvider
{
public object Value
{
get
{
var length = PerfNotes.BenchArraySize / 2;
var job = new SquareRootRecip()
{
a = new NativeArray<float>(length, Allocator.Persistent),
b = new NativeArray<float>(length, Allocator.Persistent)
};
var random = new System.Random(0);
for (int i = 0; i < length; i++)
{
job.a[i] = random.Next();
}
return job;
}
}
}
public void Execute()
{
for (int i = 0; i < a.Length; ++i)
{
b[i] = math.rsqrt(a[i]);
}
}
public void Dispose()
{
a.Dispose();
b.Dispose();
}
}
internal struct RedundantStore : IJob, IDisposable
{
public int sum;
public NativeArray<int> a;
public struct Provider : IArgumentProvider
{
public object Value
{
get
{
var length = PerfNotes.BenchArraySize * 2;
var job = new RedundantStore()
{
a = new NativeArray<int>(length, Allocator.Persistent)
};
var random = new System.Random(0);
for (int i = 0; i < length; i++)
{
job.a[i] = random.Next();
}
return job;
}
}
}
public void Execute()
{
for (int i = 0; i < a.Length; ++i)
{
sum += a[i];
}
}
public void Dispose()
{
a.Dispose();
}
}
internal struct RedundantStoreWorkaround : IJob, IDisposable
{
public int sum;
public NativeArray<int> a;
public struct Provider : IArgumentProvider
{
public object Value
{
get
{
var length = PerfNotes.BenchArraySize * 2;
var job = new RedundantStoreWorkaround()
{
a = new NativeArray<int>(length, Allocator.Persistent)
};
var random = new System.Random(0);
for (int i = 0; i < length; i++)
{
job.a[i] = random.Next();
}
return job;
}
}
}
public void Execute()
{
for (int i = 0; i < a.Length; ++i)
{
sum += a[i];
}
}
public void Dispose()
{
a.Dispose();
}
}
/* TODO: Is from the notes, but we don't have have a mock of IComponentData
public struct SimpleComponentData : IComponentData
{
public int val;
}
public struct SimpleComponentDataTest : IJob
{
public ComponentDataArray<SimpleComponentData> a;
public void Execute()
{
for (int i = 0; i < a.Length; ++i)
{
var item = a[i];
item.val += 9999;
a[i] = item;
}
}
}
*/
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f0226688e0613b4f91533ad8d9d4ef99
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,542 @@
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using Unity.Jobs;
using Unity.Mathematics;
[assembly: InternalsVisibleTo("Burst.Benchmarks")]
namespace UnityBenchShared
{
internal struct Sphere
{
private float x, y, z, r;
public Sphere(float x, float y, float z, float r)
{
this.x = x;
this.y = y;
this.z = z;
this.r = r;
}
public bool Intersects(Sphere other)
{
float dx = x - other.x;
float dy = y - other.y;
float dz = z - other.z;
float rs = r + other.r;
return dx * dx + dy * dy + dz * dz < (rs * rs);
}
}
internal static class SphereCulling
{
public static int BenchCount = 128 * 1024 + 3;
}
internal interface IJob<T> : IJob
{
T Result { get; set; }
}
/// <summary>
/// Simple AOS with a Sphere struct using plain floats
/// </summary>
internal struct SphereCullingAOSJob : IJob<bool>, IDisposable
{
public Sphere Against;
[ReadOnly] public NativeArray<Sphere> Spheres;
[MarshalAs(UnmanagedType.U1)]
private bool result;
public bool Result
{
get => result;
set => result = value;
}
public void Execute()
{
bool result = false;
for (int i = 0; i < Spheres.Length; ++i)
{
result |= Spheres[i].Intersects(Against);
}
Result = result;
}
public struct Provider : IArgumentProvider
{
public object Value
{
get
{
int length = SphereCulling.BenchCount * 2;
var job = new SphereCullingAOSJob()
{
Spheres = new NativeArray<Sphere>(length, Allocator.Persistent),
Against = new Sphere(0, 0, 0, 1)
};
var random = new System.Random(0);
for (int i = 0; i < job.Spheres.Length; i++)
{
// Most don't intersects
var x = random.Next(100) + 3.0f;
if (i == job.Spheres.Length / 2)
{
// only this one
x = 0.5f;
}
job.Spheres[i] = new Sphere(x, x, x, 1.0f);
}
return job;
}
}
}
public void Dispose()
{
Spheres.Dispose();
}
}
/// <summary>
/// Simple AOS with a float4 for the struct and using
/// </summary>
internal struct SphereCullingFloat4AOSJob : IJob<bool>, IDisposable
{
public float4 Against;
[ReadOnly]
public NativeArray<float4> Spheres;
[MarshalAs(UnmanagedType.U1)]
private bool result;
public bool Result
{
get => result;
set => result = value;
}
public static bool Intersects(float4 value, float4 other)
{
float rs = value.w + other.w;
return math.dot(value.xyz, other.xyz) < (rs * rs);
}
public void Execute()
{
bool result = false;
for (int i = 0; i < Spheres.Length; ++i)
{
result |= Intersects(Spheres[i], Against);
}
Result = result;
}
public struct Provider : IArgumentProvider
{
public object Value
{
get
{
int length = SphereCulling.BenchCount;
var job = new SphereCullingFloat4AOSJob()
{
Spheres = new NativeArray<float4>(length, Allocator.Persistent),
Against = new float4(0, 0, 0, 1)
};
var random = new System.Random(0);
for (int i = 0; i < job.Spheres.Length; i++)
{
// Most don't intersects
var x = random.Next(100) + 3.0f;
if (i == job.Spheres.Length / 2)
{
// only this one
x = 0.5f;
}
job.Spheres[i] = new float4(x, x, x, 1.0f);
}
return job;
}
}
}
public void Dispose()
{
Spheres.Dispose();
}
}
/// <summary>
/// Simple SOA with 4 NativeArray for X,Y,Z,R
/// </summary>
internal struct SphereCullingSOAJob : IJob<bool>, IDisposable
{
[ReadOnly] public NativeArray<float> X;
[ReadOnly] public NativeArray<float> Y;
[ReadOnly] public NativeArray<float> Z;
[ReadOnly] public NativeArray<float> R;
public float4 Against;
[MarshalAs(UnmanagedType.U1)]
private bool result;
public bool Result
{
get => result;
set => result = value;
}
public void Execute()
{
bool result = false;
for (int i = 0; i < X.Length; ++i)
{
float dx = X[i] - Against.x;
float dy = Y[i] - Against.y;
float dz = Z[i] - Against.z;
float rs = R[i] + Against.w;
result |= dx * dx + dy * dy + dz * dz < (rs * rs);
}
Result = result;
}
public struct Provider : IArgumentProvider
{
public object Value
{
get
{
int length = SphereCulling.BenchCount * 2;
var job = new SphereCullingSOAJob()
{
X = new NativeArray<float>(length, Allocator.Persistent),
Y = new NativeArray<float>(length, Allocator.Persistent),
Z = new NativeArray<float>(length, Allocator.Persistent),
R = new NativeArray<float>(length, Allocator.Persistent),
Against = new float4(0, 0, 0, 1)
};
var random = new System.Random(0);
for (int i = 0; i < job.X.Length; i++)
{
// Most don't intersects
var x = random.Next(100) + 3.0f;
if (i == job.X.Length / 2)
{
// only this one
x = 0.5f;
}
job.X[i] = x;
job.Y[i] = x;
job.Z[i] = x;
job.R[i] = 1;
}
return job;
}
}
}
public void Dispose()
{
X.Dispose();
Y.Dispose();
Z.Dispose();
R.Dispose();
}
}
/// <summary>
/// SOA with chunks of x,y,z,r using `float4`
/// </summary>
internal struct SphereCullingChunkSOAJob : IJob<bool>, IDisposable
{
public struct Chunk
{
public float4 X;
public float4 Y;
public float4 Z;
public float4 R;
}
[ReadOnly] public NativeArray<Chunk> Chunks;
public float4 Against;
[MarshalAs(UnmanagedType.U1)]
private bool result;
public bool Result
{
get => result;
set => result = value;
}
public void Execute()
{
bool result = false;
for (int i = 0; i < Chunks.Length; ++i)
{
var chunk = Chunks[i];
for (int j = 0; j < 4; j++)
{
float dx = chunk.X[j] - Against.x;
float dy = chunk.Y[j] - Against.y;
float dz = chunk.Z[j] - Against.z;
float rs = chunk.R[j] + Against.w;
result |= dx * dx + dy * dy + dz * dz < (rs * rs);
}
}
Result = result;
}
public struct Provider : IArgumentProvider
{
public object Value
{
get
{
// Approximate a similar batch
int length = ((SphereCulling.BenchCount * 2) + 4) / 4;
var job = new SphereCullingChunkSOAJob
{
Chunks = new NativeArray<SphereCullingChunkSOAJob.Chunk>(length, Allocator.Persistent),
Against = new float4(0, 0, 0, 1)
};
var random = new System.Random(0);
for (int i = 0; i < job.Chunks.Length; i++)
{
var chunk = job.Chunks[i];
for (int j = 0; j < 4; j++)
{
// Most don't intersects
var x = random.Next(100) + 3.0f;
if (i == job.Chunks.Length / 2)
{
// only this one
x = 0.5f;
}
chunk.X[j] = x;
chunk.Y[j] = x;
chunk.Z[j] = x;
chunk.R[j] = 1;
}
job.Chunks[i] = chunk;
}
return job;
}
}
}
public void Dispose()
{
Chunks.Dispose();
}
}
/// <summary>
/// SOA with chunks of x,y,z,r using `fixed float x[4]`
/// </summary>
internal struct SphereCullingChunkFixedSOAJob : IJob<bool>, IDisposable
{
public unsafe struct Chunk
{
public fixed float X[4];
public fixed float Y[4];
public fixed float Z[4];
public fixed float R[4];
}
[ReadOnly] public NativeArray<Chunk> Chunks;
public float4 Against;
[MarshalAs(UnmanagedType.U1)]
private bool result;
public bool Result
{
get => result;
set => result = value;
}
public unsafe void Execute()
{
bool result = false;
for (int i = 0; i < Chunks.Length; ++i)
{
var chunk = Chunks[i];
for (int j = 0; j < 4; j++)
{
float dx = chunk.X[j] - Against.x;
float dy = chunk.Y[j] - Against.y;
float dz = chunk.Z[j] - Against.z;
float rs = chunk.R[j] + Against.w;
result |= dx * dx + dy * dy + dz * dz < (rs * rs);
}
}
Result = result;
}
public struct Provider : IArgumentProvider
{
public unsafe object Value
{
get
{
// Approximate a similar batch
int length = ((SphereCulling.BenchCount) + 4) / 2;
var job = new SphereCullingChunkFixedSOAJob
{
Chunks = new NativeArray<Chunk>(length, Allocator.Persistent),
Against = new float4(0, 0, 0, 1)
};
var random = new System.Random(0);
for (int i = 0; i < job.Chunks.Length; i++)
{
var chunk = job.Chunks[i];
for (int j = 0; j < 4; j++)
{
// Most don't intersects
var x = random.Next(100) + 3.0f;
if (i == job.Chunks.Length / 2)
{
// only this one
x = 0.5f;
}
chunk.X[j] = x;
chunk.Y[j] = x;
chunk.Z[j] = x;
chunk.R[j] = 1;
}
job.Chunks[i] = chunk;
}
return job;
}
}
}
public void Dispose()
{
Chunks.Dispose();
}
}
/// <summary>
/// </summary>
internal struct SphereCullingChunkSOAManualJob : IJob<bool>, IDisposable
{
public struct Chunk
{
public float4 X;
public float4 Y;
public float4 Z;
public float4 R;
}
[ReadOnly] public NativeArray<Chunk> Chunks;
public float4 Against;
[MarshalAs(UnmanagedType.U1)]
private bool result;
public bool Result
{
get => result;
set => result = value;
}
public void Execute()
{
bool4 result = false;
for (int i = 0; i < Chunks.Length; ++i)
{
var chunk = Chunks[i];
float4 dx = chunk.X - Against.x;
float4 dy = chunk.Y - Against.y;
float4 dz = chunk.Z - Against.z;
float4 rs = chunk.R + Against.w;
result |= dx * dx + dy * dy + dz * dz < (rs * rs);
}
Result = math.any(result);
}
public struct Provider : IArgumentProvider
{
public object Value
{
get
{
// Approximate a similar batch
int length = (SphereCulling.BenchCount + 4) / 4;
var job = new SphereCullingChunkSOAManualJob
{
Chunks = new NativeArray<SphereCullingChunkSOAManualJob.Chunk>(length, Allocator.Persistent),
Against = new float4(0, 0, 0, 1)
};
var random = new System.Random(0);
for (int i = 0; i < job.Chunks.Length; i++)
{
var chunk = job.Chunks[i];
for (int j = 0; j < 4; j++)
{
// Most don't intersects
var x = random.Next(100) + 3.0f;
if (i == job.Chunks.Length / 2)
{
// only this one
x = 0.5f;
}
chunk.X[j] = x;
chunk.Y[j] = x;
chunk.Z[j] = x;
chunk.R[j] = 1;
}
job.Chunks[i] = chunk;
}
return job;
}
}
}
public void Dispose()
{
Chunks.Dispose();
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ed29326fcba3397394b33a09e46df489
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,56 @@
using System;
using System.Runtime.CompilerServices;
using Unity.Collections;
using Unity.Jobs;
[assembly: InternalsVisibleTo("Burst.Benchmarks")]
namespace UnityBenchShared
{
internal struct SumNumbersTest : IJob, IDisposable
{
public const int Count = 10000000;
public NativeArray<float> output;
[ReadOnly]
public NativeArray<float> a;
[ReadOnly]
public NativeArray<float> b;
public void Execute()
{
for (int i = 0; i < Count; ++i)
{
output[i] = a[i] + b[i];
}
}
public struct Provider : IArgumentProvider
{
public object Value
{
get
{
var job = new SumNumbersTest();
job.output = new NativeArray<float>(Count, Allocator.Persistent);
job.a = new NativeArray<float>(Count, Allocator.Persistent);
job.b = new NativeArray<float>(Count, Allocator.Persistent);
for (int i = 0; i < Count; i++)
{
job.a[i] = i;
}
return job;
}
}
}
public void Dispose()
{
output.Dispose();
a.Dispose();
b.Dispose();
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4e813577ac9c3de8947a14eb8c3ce7ea
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant: