//[/commonTester] //[commonPerfTester] public static void Performance(ISimulatorTester simulator, int numBodies) { const float clusterScale = 1.0f; const float velocityScale = 1.0f; const float deltaTime = 0.001f; const float softeningSquared = 0.00125f; const float damping = 0.9995f; const int steps = 10; Console.WriteLine("Perfomancing {0} with {1} bodies...", simulator.Description, numBodies); float4[] pos, vel; BodyInitializer.Initialize(new BodyInitializer1(), clusterScale, velocityScale, numBodies, out pos, out vel); simulator.Integrate(pos, vel, numBodies, deltaTime, softeningSquared, damping, steps); }
static public void Initialize(BodyInitializer initializer, float clusterScale, float velocityScale, int numBodies, out float4[] positions, out float4[] velocities) { var pscale = clusterScale * Math.Max(1.0f, numBodies / 1024.0f); var vscale = velocityScale * pscale; initializer.NumBodies = numBodies; initializer.PScale = pscale; initializer.VScale = vscale; positions = Enumerable.Range(0, numBodies).Select(initializer.Position).ToArray(); velocities = positions.Select(initializer.Velocity).ToArray(); // now we try to adjust velocity to make total momentum = zero. var momentums = velocities.Select(Momentum).ToArray(); var totalMomentum = momentums.Aggregate(new float4(0.0f, 0.0f, 0.0f, 0.0f), (accum, momentum) => new float4(accum.x + momentum.x, accum.y + momentum.y, accum.z + momentum.z, accum.w + momentum.w)); Console.WriteLine("total momentum and mass 0 = {0}", totalMomentum); var len = velocities.Length; // adjust velocities velocities = velocities.Select((vel, i) => new float4( vel.x - totalMomentum.x / len / vel.w, vel.y - totalMomentum.y / len / vel.w, vel.z - totalMomentum.z / len / vel.w, vel.w)).ToArray(); // see total momentum after adjustment momentums = velocities.Select(Momentum).ToArray(); totalMomentum = momentums.Aggregate(new float4(0.0f, 0.0f, 0.0f, 0.0f), (accum, momentum) => new float4(accum.x + momentum.x, accum.y + momentum.y, accum.z + momentum.z, accum.w + momentum.w)); Console.WriteLine("total momentum and mass 1 = {0}", totalMomentum); }
//[commonTester] public static void Test( BodyInitializer initializer, ISimulatorTester expectedSimulator, ISimulatorTester actualSimulator, int numBodies) { const float clusterScale = 1.0f; const float velocityScale = 1.0f; const float deltaTime = 0.001f; const float softeningSquared = 0.00125f; const float damping = 0.9995f; const int steps = 5; Console.WriteLine("Testing {0} against {1} with {2} bodies...", actualSimulator.Description, expectedSimulator.Description, numBodies); Console.WriteLine("Using body initializer {0}...", initializer); float4[] expectedPos, expectedVel; BodyInitializer.Initialize(initializer, clusterScale, velocityScale, numBodies, out expectedPos, out expectedVel); for (var i = 0; i < steps; i++) { const double tol = 1e-5; var actualPos = new float4[numBodies]; var actualVel = new float4[numBodies]; Array.Copy(expectedPos, actualPos, numBodies); Array.Copy(expectedVel, actualVel, numBodies); expectedSimulator.Integrate(expectedPos, expectedVel, numBodies, deltaTime, softeningSquared, damping, 1); actualSimulator.Integrate(actualPos, actualVel, numBodies, deltaTime, softeningSquared, damping, 1); for (var j = 0; j < expectedPos.Length; j++) { Assert.AreEqual(actualPos[j].x, expectedPos[j].x, tol); Assert.AreEqual(actualPos[j].y, expectedPos[j].y, tol); Assert.AreEqual(actualPos[j].z, expectedPos[j].z, tol); Assert.AreEqual(actualPos[j].w, expectedPos[j].w, tol); } } }
static public void Initialize(BodyInitializer initializer, float clusterScale, float velocityScale, int numBodies, out float4[] positions, out float4[] velocities) { var pscale = clusterScale*Math.Max(1.0f, numBodies/1024.0f); var vscale = velocityScale*pscale; initializer.NumBodies = numBodies; initializer.PScale = pscale; initializer.VScale = vscale; positions = Enumerable.Range(0, numBodies).Select(initializer.Position).ToArray(); velocities = positions.Select(initializer.Velocity).ToArray(); // now we try to adjust velocity to make total momentum = zero. var momentums = velocities.Select(Momentum).ToArray(); var totalMomentum = momentums.Aggregate(new float4(0.0f, 0.0f, 0.0f, 0.0f), (accum, momentum) => new float4(accum.x + momentum.x, accum.y + momentum.y, accum.z + momentum.z, accum.w + momentum.w)); Console.WriteLine("total momentum and mass 0 = {0}", totalMomentum); var len = velocities.Length; // adjust velocities velocities = velocities.Select((vel, i) => new float4( vel.x - totalMomentum.x / len / vel.w, vel.y - totalMomentum.y / len / vel.w, vel.z - totalMomentum.z / len / vel.w, vel.w)).ToArray(); // see total momentum after adjustment momentums = velocities.Select(Momentum).ToArray(); totalMomentum = momentums.Aggregate(new float4(0.0f, 0.0f, 0.0f, 0.0f), (accum, momentum) => new float4(accum.x + momentum.x, accum.y + momentum.y, accum.z + momentum.z, accum.w + momentum.w)); Console.WriteLine("total momentum and mass 1 = {0}", totalMomentum); }
//[/LockPositions] public SimWindow() : base(800, 600, GraphicsMode.Default, "Gravitational n-body simulation") { _numBodies = 256 * 64; const float clusterScale = 1.0f; const float velocityScale = 1.0f; _deltaTime = 0.001f; _softeningSquared = 0.00125f; _damping = 0.9995f; //[CreateWorker] _worker = Worker.CreateByFunc(Generate); //[/CreateWorker] _stopwatch = Stopwatch.StartNew(); _fpsCalcLag = 128; _frameCounter = 0; //[CreateSimulatros] _simulators = new Queue <ISimulator>(); var target = GPUModuleTarget.Worker(_worker); var simulatorGpuDynamicBlockSizeModule = new GpuDynamicSimulatorModule(target); // need dispose var simulatorGpuDynamicBlockSize64 = simulatorGpuDynamicBlockSizeModule.Create(64); var simulatorGpuDynamicBlockSize128 = simulatorGpuDynamicBlockSizeModule.Create(128); var simulatorGpuDynamicBlockSize256 = simulatorGpuDynamicBlockSizeModule.Create(256); var simulatorGpuDynamicBlockSize512 = simulatorGpuDynamicBlockSizeModule.Create(512); var simulatorGpuStaticBlockSizeModule64 = new GpuStaticSimulatorModule64(target); // need dispose var simulatorGpuStaticBlockSizeModule128 = new GpuStaticSimulatorModule128(target); // need dispose var simulatorGpuStaticBlockSizeModule256 = new GpuStaticSimulatorModule256(target); // need dispose var simulatorGpuStaticBlockSizeModule512 = new GpuStaticSimulatorModule512(target); // need dispose // First, enquene one simulator which is 256 blocksize so we can compare with C code for performance. _simulators.Enqueue(simulatorGpuStaticBlockSizeModule256); // Enqueue several dynamic block size simulators. _simulators.Enqueue(simulatorGpuDynamicBlockSize64); _simulators.Enqueue(simulatorGpuDynamicBlockSize128); _simulators.Enqueue(simulatorGpuDynamicBlockSize256); _simulators.Enqueue(simulatorGpuDynamicBlockSize512); // Enqueue several static block size simulators. _simulators.Enqueue(simulatorGpuStaticBlockSizeModule64); _simulators.Enqueue(simulatorGpuStaticBlockSizeModule128); _simulators.Enqueue(simulatorGpuStaticBlockSizeModule256); _simulators.Enqueue(simulatorGpuStaticBlockSizeModule512); // We do not enqueue any cpu simulator as it is much too slow. //_simulators.Enqueue(new CpuSimulator(_worker, _numBodies)); _disposeSimulators = () => { simulatorGpuDynamicBlockSizeModule.Dispose(); simulatorGpuStaticBlockSizeModule64.Dispose(); simulatorGpuStaticBlockSizeModule128.Dispose(); simulatorGpuStaticBlockSizeModule256.Dispose(); simulatorGpuStaticBlockSizeModule512.Dispose(); }; _simulator = _simulators.Dequeue(); //[/CreateSimulatros] //[CreateBuffers] _buffers = new uint[2]; for (var i = 0; i < _buffers.Length; i++) { _buffers[i] = 0; } GL.GenBuffers(_buffers.Length, _buffers); foreach (var buffer in _buffers) { GL.BindBuffer(BufferTarget.ArrayBuffer, buffer); GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(Microsoft.FSharp.Core.Operators.SizeOf <float4>() * _numBodies), IntPtr.Zero, BufferUsageHint.DynamicDraw); var size = 0; unsafe { GL.GetBufferParameter(BufferTarget.ArrayBuffer, BufferParameterName.BufferSize, &size); } if (size != Microsoft.FSharp.Core.Operators.SizeOf <float4>() * _numBodies) { throw new Exception("Pixel Buffer Object allocation failed!"); } GL.BindBuffer(BufferTarget.ArrayBuffer, 0); CUDAInterop.cuSafeCall(CUDAInterop.cuGLRegisterBufferObject(buffer)); } _resources = new IntPtr[_buffers.Length]; for (var i = 0; i < _buffers.Length; i++) { var res = IntPtr.Zero; unsafe { CUDAInterop.cuSafeCall(CUDAInterop.cuGraphicsGLRegisterBuffer(&res, _buffers[i], 0u)); } _resources[i] = res; } //[/CreateBuffers] //[FinalizeGL] _vel = _worker.Malloc <float4>(_numBodies); float4[] hpos, hvel; BodyInitializer.Initialize(new BodyInitializer3(), clusterScale, velocityScale, _numBodies, out hpos, out hvel); _worker.Scatter(hvel, _vel.Ptr, Microsoft.FSharp.Core.FSharpOption <int> .None, Microsoft.FSharp.Core.FSharpOption <int> .None); LockPos( (pos0, pos1) => _worker.Scatter(hpos, pos1, Microsoft.FSharp.Core.FSharpOption <int> .None, Microsoft.FSharp.Core.FSharpOption <int> .None)); Help(); Description(); //[/FinalizeGL] }