Skip to content

Instantly share code, notes, and snippets.

@ZeroStride
Created April 4, 2010 21:18
Show Gist options
  • Save ZeroStride/355711 to your computer and use it in GitHub Desktop.
Save ZeroStride/355711 to your computer and use it in GitHub Desktop.
using System;
using System.Diagnostics;
using Microsoft.Xna.Framework;
// SoA Vector4
// this test uses a simple array of Vector4's to do batched processing of 4 particles at a time
namespace XNA360MathTest
{
static class Program
{
static unsafe void Main(string[] args)
{
const int NumParticles = 3200000;
const float dt = 0.04f;
const int NumSimulationRuns = 50;
int NumBatches = NumParticles / 4;
Vector4[] px_stream = new Vector4[NumBatches];
Vector4[] py_stream = new Vector4[NumBatches];
Vector4[] pz_stream = new Vector4[NumBatches];
Vector4[] vx_stream = new Vector4[NumBatches];
Vector4[] vy_stream = new Vector4[NumBatches];
Vector4[] vz_stream = new Vector4[NumBatches];
Vector4[] time_stream = new Vector4[NumBatches];
Random rnd = new Random();
for (int i = 0; i < NumBatches; i++)
{
px_stream[i].X = (float)rnd.NextDouble();
px_stream[i].Y = (float)rnd.NextDouble();
px_stream[i].Z = (float)rnd.NextDouble();
px_stream[i].W = (float)rnd.NextDouble();
py_stream[i].X = (float)rnd.NextDouble();
py_stream[i].Y = (float)rnd.NextDouble();
py_stream[i].Z = (float)rnd.NextDouble();
py_stream[i].W = (float)rnd.NextDouble();
pz_stream[i].X = (float)rnd.NextDouble();
pz_stream[i].Y = (float)rnd.NextDouble();
pz_stream[i].Z = (float)rnd.NextDouble();
pz_stream[i].W = (float)rnd.NextDouble();
vx_stream[i].X = (float)rnd.NextDouble();
vx_stream[i].Y = (float)rnd.NextDouble();
vx_stream[i].Z = (float)rnd.NextDouble();
vx_stream[i].W = (float)rnd.NextDouble();
vy_stream[i].X = (float)rnd.NextDouble();
vy_stream[i].Y = (float)rnd.NextDouble();
vy_stream[i].Z = (float)rnd.NextDouble();
vy_stream[i].W = (float)rnd.NextDouble();
vz_stream[i].X = (float)rnd.NextDouble();
vz_stream[i].Y = (float)rnd.NextDouble();
vz_stream[i].Z = (float)rnd.NextDouble();
vz_stream[i].W = (float)rnd.NextDouble();
time_stream[i].X = (float)rnd.NextDouble();
time_stream[i].Y = (float)rnd.NextDouble();
time_stream[i].Z = (float)rnd.NextDouble();
time_stream[i].W = (float)rnd.NextDouble();
}
Vector4 dt_v = new Vector4(dt);
Vector4 dx, dy, dz;
Stopwatch hptimer = new Stopwatch();
float simAvg = 0.0f;
float simMin = float.PositiveInfinity;
float simMax = 0.0f;
for (int j = 0; j < NumSimulationRuns; j++)
{
hptimer.Reset();
hptimer.Start();
for (int i = 0; i < NumBatches; i++)
{
Vector4.Multiply(ref vx_stream[i], ref dt_v, out dx);
Vector4.Multiply(ref vy_stream[i], ref dt_v, out dy);
Vector4.Multiply(ref vz_stream[i], ref dt_v, out dz);
Vector4.Add(ref dx, ref px_stream[i], out px_stream[i]);
Vector4.Add(ref dy, ref py_stream[i], out py_stream[i]);
Vector4.Add(ref dz, ref pz_stream[i], out pz_stream[i]);
Vector4.Subtract(ref time_stream[i], ref dt_v, out time_stream[i]);
}
hptimer.Stop();
float elapsedMS = hptimer.ElapsedTicks * 1000.0f / (float)Stopwatch.Frequency;
simAvg += elapsedMS;
simMin = (simMin > elapsedMS ? elapsedMS : simMin);
simMax = (simMax < elapsedMS ? elapsedMS : simMax);
}
simAvg /= NumSimulationRuns;
string outpt = "Average: " + simAvg + " Min: " + simMin + " Max: " + simMax;
Console.WriteLine(outpt); // Set breakpoint here
}
}
}
using System;
using System.Diagnostics;
using Microsoft.Xna.Framework;
// Unsafe SoA Float To Vector4
// this test uses an array of float's and casts them to Vector4's to do batched processing of 4 particles at a time
namespace XNA360MathTest
{
static class Program
{
static unsafe void Main(string[] args)
{
const int NumParticles = 3200000;
const float dt = 0.04f;
const int NumSimulationRuns = 50;
int NumBatches = NumParticles / 4;
float[] px_stream = new float[NumParticles];
float[] py_stream = new float[NumParticles];
float[] pz_stream = new float[NumParticles];
float[] vx_stream = new float[NumParticles];
float[] vy_stream = new float[NumParticles];
float[] vz_stream = new float[NumParticles];
float[] time_stream = new float[NumParticles];
Random rnd = new Random();
for (int i = 0; i < NumParticles; i++)
{
px_stream[i] = (float)rnd.NextDouble();
py_stream[i] = (float)rnd.NextDouble();
pz_stream[i] = (float)rnd.NextDouble();
vx_stream[i] = (float)rnd.NextDouble();
vy_stream[i] = (float)rnd.NextDouble();
vz_stream[i] = (float)rnd.NextDouble();
time_stream[i] = (float)rnd.NextDouble();
}
Vector4 dt_v = new Vector4(dt);
Vector4 dx, dy, dz;
Stopwatch hptimer = new Stopwatch();
float simAvg = 0.0f;
float simMin = float.PositiveInfinity;
float simMax = 0.0f;
fixed (float* vxptr = vx_stream)
{
fixed (float* vyptr = vy_stream)
{
fixed (float* vzptr = vz_stream)
{
fixed (float* pxptr = px_stream)
{
fixed (float* pyptr = py_stream)
{
fixed (float* pzptr = pz_stream)
{
fixed (float* tptr = time_stream)
{
for (int j = 0; j < NumSimulationRuns; j++)
{
Vector4* vx = (Vector4*)vxptr;
Vector4* vy = (Vector4*)vyptr;
Vector4* vz = (Vector4*)vzptr;
Vector4* px = (Vector4*)pxptr;
Vector4* py = (Vector4*)pyptr;
Vector4* pz = (Vector4*)pzptr;
Vector4* time = (Vector4*)tptr;
hptimer.Reset();
hptimer.Start();
for (int i = 0; i < NumBatches; i++)
{
Vector4.Multiply(ref *vx, ref dt_v, out dx);
Vector4.Multiply(ref *vy, ref dt_v, out dy);
Vector4.Multiply(ref *vz, ref dt_v, out dz);
Vector4.Add(ref dx, ref *px, out *px);
Vector4.Add(ref dy, ref *py, out *py);
Vector4.Add(ref dz, ref *pz, out *pz);
Vector4.Subtract(ref *time, ref dt_v, out *time);
vx++;
vy++;
vz++;
px++;
py++;
pz++;
time++;
}
hptimer.Stop();
float elapsedMS = hptimer.ElapsedTicks * 1000.0f / (float)Stopwatch.Frequency;
simAvg += elapsedMS;
simMin = (simMin > elapsedMS ? elapsedMS : simMin);
simMax = (simMax < elapsedMS ? elapsedMS : simMax);
}
simAvg /= NumSimulationRuns;
string outpt = "Average: " + simAvg + " Min: " + simMin + " Max: " + simMax;
Console.WriteLine(outpt); // Set breakpoint here
}
}
}
}
}
}
}
}
}
}
using System;
using System.Diagnostics;
using Microsoft.Xna.Framework;
// SoA Float
// this test uses an array of float's and processes each particle individually
namespace XNA360MathTest
{
static class Program
{
static unsafe void Main(string[] args)
{
const int NumParticles = 3200000;
const float dt = 0.04f;
const int NumSimulationRuns = 50;
float[] px_stream = new float[NumParticles];
float[] py_stream = new float[NumParticles];
float[] pz_stream = new float[NumParticles];
float[] vx_stream = new float[NumParticles];
float[] vy_stream = new float[NumParticles];
float[] vz_stream = new float[NumParticles];
float[] time_stream = new float[NumParticles];
Random rnd = new Random();
for (int i = 0; i < NumParticles; i++)
{
px_stream[i] = (float)rnd.NextDouble();
py_stream[i] = (float)rnd.NextDouble();
pz_stream[i] = (float)rnd.NextDouble();
vx_stream[i] = (float)rnd.NextDouble();
vy_stream[i] = (float)rnd.NextDouble();
vz_stream[i] = (float)rnd.NextDouble();
time_stream[i] = (float)rnd.NextDouble();
}
Stopwatch hptimer = new Stopwatch();
float simAvg = 0.0f;
float simMin = float.PositiveInfinity;
float simMax = 0.0f;
for (int j = 0; j < NumSimulationRuns; j++)
{
hptimer.Reset();
hptimer.Start();
for (int i = 0; i < NumParticles; i++)
{
px_stream[i] = vx_stream[i] * dt + px_stream[i];
py_stream[i] = vy_stream[i] * dt + py_stream[i];
pz_stream[i] = vz_stream[i] * dt + pz_stream[i];
time_stream[i] -= dt;
}
hptimer.Stop();
float elapsedMS = hptimer.ElapsedTicks * 1000.0f / (float)Stopwatch.Frequency;
simAvg += elapsedMS;
simMin = (simMin > elapsedMS ? elapsedMS : simMin);
simMax = (simMax < elapsedMS ? elapsedMS : simMax);
}
simAvg /= NumSimulationRuns;
string outpt = "Average: " + simAvg + " Min: " + simMin + " Max: " + simMax;
Console.WriteLine(outpt); // Set breakpoint here
}
}
}
using System;
using System.Diagnostics;
using Microsoft.Xna.Framework;
// Unsafe SoA Float
// this test uses an array of float's as pointers and processes each particle individually
namespace XNA360MathTest
{
static class Program
{
static unsafe void Main(string[] args)
{
const int NumParticles = 3200000;
const float dt = 0.04f;
const int NumSimulationRuns = 50;
float[] px_stream = new float[NumParticles];
float[] py_stream = new float[NumParticles];
float[] pz_stream = new float[NumParticles];
float[] vx_stream = new float[NumParticles];
float[] vy_stream = new float[NumParticles];
float[] vz_stream = new float[NumParticles];
float[] time_stream = new float[NumParticles];
Random rnd = new Random();
for (int i = 0; i < NumParticles; i++)
{
px_stream[i] = (float)rnd.NextDouble();
py_stream[i] = (float)rnd.NextDouble();
pz_stream[i] = (float)rnd.NextDouble();
vx_stream[i] = (float)rnd.NextDouble();
vy_stream[i] = (float)rnd.NextDouble();
vz_stream[i] = (float)rnd.NextDouble();
time_stream[i] = (float)rnd.NextDouble();
}
Stopwatch hptimer = new Stopwatch();
float simAvg = 0.0f;
float simMin = float.PositiveInfinity;
float simMax = 0.0f;
fixed (float* vxptr = vx_stream)
{
fixed (float* vyptr = vy_stream)
{
fixed (float* vzptr = vz_stream)
{
fixed (float* pxptr = px_stream)
{
fixed (float* pyptr = py_stream)
{
fixed (float* pzptr = pz_stream)
{
fixed (float* tptr = time_stream)
{
for (int j = 0; j < NumSimulationRuns; j++)
{
float* vx = vxptr;
float* vy = vyptr;
float* vz = vzptr;
float* px = pxptr;
float* py = pyptr;
float* pz = pzptr;
float* time = tptr;
hptimer.Reset();
hptimer.Start();
for (int i = 0; i < NumParticles; i++)
{
*px = *vx * dt + *px;
*py = *vy * dt + *py;
*pz = *vz * dt + *pz;
*time -= dt;
vx++;
vy++;
vz++;
px++;
py++;
pz++;
time++;
}
hptimer.Stop();
float elapsedMS = hptimer.ElapsedTicks * 1000.0f / (float)Stopwatch.Frequency;
simAvg += elapsedMS;
simMin = (simMin > elapsedMS ? elapsedMS : simMin);
simMax = (simMax < elapsedMS ? elapsedMS : simMax);
}
simAvg /= NumSimulationRuns;
string outpt = "Average: " + simAvg + " Min: " + simMin + " Max: " + simMax;
Console.WriteLine(outpt); // Set breakpoint here
}
}
}
}
}
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment