Changes

Jump to: navigation, search

GPU610/Cosmosis

44,403 bytes added, 15:10, 13 April 2013
Dynamic Shared Memory (not implemented)
[mailto:nbguzman@myseneca.ca,jsantos13@myseneca.ca,acraig1@myseneca.ca,cfbale@myseneca.ca?subject=dps915-gpu610 Email All]
== Repo Links ==* Repo - [https://code.google.com/p/gpu-nbody/code.google.com/p/gpu-nbody]* SFML - [http://www.sfml-dev.org/ www.sfml-dev.org/]* SSE - [https://en.wikipedia.org/wiki/Streaming_SIMD_Extensions en.wikipedia.org/wiki/Streaming_SIMD_Extensions]* N-Body - [http://www.cs.princeton.edu/courses/archive/fall07/cos126/assignments/nbody.html cs.princeton.edu/courses/archive/fall07/cos126/assignments/nbody.html]* Grids - [http://www.resultsovercoffee.com/2011/02/cuda-blocks-and-grids.html resultsovercoffee.com/2011/02/cuda-blocks-and-grids.html]
== Progress ==
=== Assignment 1 ===
For our assignment 1, we are looking into finding and N-body simulator. All of us in the group have agreed to find 1 each, and after profiling them, we will choose the most inefficient one to parallelize.
 
====Alex's Profiling Findings====
=== Assignment 2 ===
We decided to use the N-Body simulator that Clinton profiled for assignment 2.
 
==== Baseline ====
The following profiles were made under the following compiler and computer settings:
 
<pre>nvcc main.cpp timer.cpp sim\simbody.cu sim\simulation.cu -DWIN32 -O3</pre>
 
* i5 2500K @ 4.5Ghz
* Nvidia GTX 560Ti
* Both drawing no graphics to the screen for unbiased results.
* Random position, velocity and mass for each body.
* Brute force algorithm for calculating the forces (O(n^2)).
 
==== Profiles ====
===== Profile #1 =====
 
[[File:gpu670_cosmo_a2_prof1.png|border]]
 
For our initial profile we sampled the time difference from the CPU and GPU implementation of the N-Body brute force algorithm. The chart above describes the amount of seconds it took to compute 512 brute-force samples of the N-Body simulation, lower is better. Our findings proved to be quite impressive with a 3097% speed up on 5000 bodies using the GPU to simulate. According to Amdahl’s Law, there would be an ~8.5x speedup for a function taking up 88.46% of an application’s execution time with a graphics card that has 384 cuda cores.
 
===== Profile #2 =====
Our second profile consists of running simulations for 240 seconds to determine how many samples we achieve per second, and how many total samples we end up with after four minutes.
 
[[File:gpu670_cosmo_a2_prof2.png|border]]
 
This profile shows the unbelievable amount of speedup that we can achieve with simple parallelization. Using the CPU on Windows with SSE, we achieved an average of about 51 samples per second for a total of 12359 samples taken over a period of four minutes. With the GPU parallelization we achieved an average of 370 samples per second, with a total of 88707 samples over a period of four minutes. Therefore, giving us an average speed increase of about 7.25x per sample.
 
==== Difficulties ====
We faced many discrepant difficulties in our endeavor to transfer the code from being executed on the host to being executed on the GPU. One of the challenges faced was due to the fact that the image’s functions were within a library. Because of this we had to take the image management out of the ''Body ''class, as we could not use a thrust device vector to store the bodies because we could not make the functions the image used callable on the device. This was an annoying hurdle as we had to restructure one of our classes (''Body''), and a portion of the code within other classes (''BodyManager'' & ''Game'').
 
Another challenge we were presented with was getting nvcc to compile and link in 64-bit while using our static 32-bit SFML libraries. We ended up reverting to a dynamic-linking version of SFML and a 32-bit version of our executable. This change is only temporary until we can safely and more stably compile SFML and all of it’s dependencies''' '''using a 64-bit architecture.
 
==== Code ====
 
===== Old CPU Code =====
 
<div style='color:#000020;background:#f6f8ff;'>
<span style='color:#200080; font-weight:bold; '>void</span> Simulation<span style='color:#406080; '>::</span>Tick<span style='color:#308080; '>(</span><span style='color:#200080; font-weight:bold; '>double</span> dt<span style='color:#308080; '>)</span> <span style='color:#406080; '>{</span>
<span style='color:#003060; '>size_t</span> i <span style='color:#308080; '>=</span> <span style='color:#008c00; '>0</span><span style='color:#308080; '>,</span> j <span style='color:#308080; '>=</span> <span style='color:#008c00; '>0</span><span style='color:#406080; '>;</span>
<span style='color:#200080; font-weight:bold; '>for</span><span style='color:#308080; '>(</span>i <span style='color:#308080; '>=</span> <span style='color:#008c00; '>0</span><span style='color:#406080; '>;</span> i <span style='color:#308080; '>&lt;</span> bodies_<span style='color:#308080; '>.</span>size<span style='color:#308080; '>(</span><span style='color:#308080; '>)</span><span style='color:#406080; '>;</span> <span style='color:#308080; '>+</span><span style='color:#308080; '>+</span>i<span style='color:#308080; '>)</span> <span style='color:#406080; '>{</span>
bodies_<span style='color:#308080; '>[</span>i<span style='color:#308080; '>]</span><span style='color:#308080; '>.</span>ResetForce<span style='color:#308080; '>(</span><span style='color:#308080; '>)</span><span style='color:#406080; '>;</span>
<span style='color:#200080; font-weight:bold; '>for</span><span style='color:#308080; '>(</span>j <span style='color:#308080; '>=</span> <span style='color:#008c00; '>0</span><span style='color:#406080; '>;</span> j <span style='color:#308080; '>&lt;</span> bodies_<span style='color:#308080; '>.</span>size<span style='color:#308080; '>(</span><span style='color:#308080; '>)</span><span style='color:#406080; '>;</span> <span style='color:#308080; '>+</span><span style='color:#308080; '>+</span>j<span style='color:#308080; '>)</span> <span style='color:#406080; '>{</span>
<span style='color:#200080; font-weight:bold; '>if</span><span style='color:#308080; '>(</span>i <span style='color:#308080; '>!</span><span style='color:#308080; '>=</span> j<span style='color:#308080; '>)</span> <span style='color:#406080; '>{</span>
bodies_<span style='color:#308080; '>[</span>i<span style='color:#308080; '>]</span><span style='color:#308080; '>.</span>AddForce<span style='color:#308080; '>(</span>bodies_<span style='color:#308080; '>[</span>j<span style='color:#308080; '>]</span><span style='color:#308080; '>)</span><span style='color:#406080; '>;</span>
<span style='color:#406080; '>}</span>
<span style='color:#406080; '>}</span>
<span style='color:#406080; '>}</span>
<span style='color:#200080; font-weight:bold; '>for</span><span style='color:#308080; '>(</span>i <span style='color:#308080; '>=</span> <span style='color:#008c00; '>0</span><span style='color:#406080; '>;</span> i <span style='color:#308080; '>&lt;</span> bodies_<span style='color:#308080; '>.</span>size<span style='color:#308080; '>(</span><span style='color:#308080; '>)</span><span style='color:#406080; '>;</span> <span style='color:#308080; '>+</span><span style='color:#308080; '>+</span>i<span style='color:#308080; '>)</span> <span style='color:#406080; '>{</span>
bodies_<span style='color:#308080; '>[</span>i<span style='color:#308080; '>]</span><span style='color:#308080; '>.</span>Tick<span style='color:#308080; '>(</span>dt<span style='color:#308080; '>)</span><span style='color:#406080; '>;</span>
<span style='color:#406080; '>}</span>
<span style='color:#406080; '>}</span>
</div>
 
===== Updated Kernel Code =====
 
<div style='color:#000020;background:#f6f8ff;'>
<span style='color:#200080; font-weight:bold; '>void</span> __global__ SimCalc<span style='color:#308080; '>(</span>BodyArray a<span style='color:#308080; '>)</span><span style='color:#406080; '>{</span>
<span style='color:#200080; font-weight:bold; '>int</span> idx <span style='color:#308080; '>=</span> blockIdx<span style='color:#308080; '>.</span>x <span style='color:#308080; '>*</span> blockDim<span style='color:#308080; '>.</span>x <span style='color:#308080; '>+</span> threadIdx<span style='color:#308080; '>.</span>x<span style='color:#406080; '>;</span>
<span style='color:#200080; font-weight:bold; '>if</span> <span style='color:#308080; '>(</span>idx <span style='color:#308080; '>&lt;</span> a<span style='color:#308080; '>.</span>size<span style='color:#308080; '>)</span> <span style='color:#406080; '>{</span>
a<span style='color:#308080; '>.</span>array<span style='color:#308080; '>[</span>idx<span style='color:#308080; '>]</span><span style='color:#308080; '>.</span>ResetForce<span style='color:#308080; '>(</span><span style='color:#308080; '>)</span><span style='color:#406080; '>;</span>
<span style='color:#200080; font-weight:bold; '>for</span> <span style='color:#308080; '>(</span><span style='color:#003060; '>size_t</span> j <span style='color:#308080; '>=</span> <span style='color:#008c00; '>0</span><span style='color:#406080; '>;</span> j <span style='color:#308080; '>&lt;</span> a<span style='color:#308080; '>.</span>size<span style='color:#406080; '>;</span> <span style='color:#308080; '>+</span><span style='color:#308080; '>+</span>j<span style='color:#308080; '>)</span> <span style='color:#406080; '>{</span>
<span style='color:#200080; font-weight:bold; '>if</span> <span style='color:#308080; '>(</span>idx <span style='color:#308080; '>!</span><span style='color:#308080; '>=</span> j<span style='color:#308080; '>)</span> <span style='color:#406080; '>{</span>
a<span style='color:#308080; '>.</span>array<span style='color:#308080; '>[</span>idx<span style='color:#308080; '>]</span><span style='color:#308080; '>.</span>AddForce<span style='color:#308080; '>(</span>a<span style='color:#308080; '>.</span>array<span style='color:#308080; '>[</span>j<span style='color:#308080; '>]</span><span style='color:#308080; '>)</span><span style='color:#406080; '>;</span>
<span style='color:#406080; '>}</span>
<span style='color:#406080; '>}</span>
<span style='color:#406080; '>}</span>
<span style='color:#406080; '>}</span>
 
<span style='color:#200080; font-weight:bold; '>void</span> __global__ SimTick<span style='color:#308080; '>(</span>BodyArray a<span style='color:#308080; '>,</span> <span style='color:#200080; font-weight:bold; '>float</span> dt<span style='color:#308080; '>)</span> <span style='color:#406080; '>{</span>
<span style='color:#200080; font-weight:bold; '>int</span> idx <span style='color:#308080; '>=</span> blockIdx<span style='color:#308080; '>.</span>x <span style='color:#308080; '>*</span> blockDim<span style='color:#308080; '>.</span>x <span style='color:#308080; '>+</span> threadIdx<span style='color:#308080; '>.</span>x<span style='color:#406080; '>;</span>
<span style='color:#200080; font-weight:bold; '>if</span> <span style='color:#308080; '>(</span>idx <span style='color:#308080; '>&lt;</span> a<span style='color:#308080; '>.</span>size<span style='color:#308080; '>)</span> <span style='color:#406080; '>{</span>
a<span style='color:#308080; '>.</span>array<span style='color:#308080; '>[</span>idx<span style='color:#308080; '>]</span><span style='color:#308080; '>.</span>Tick<span style='color:#308080; '>(</span>dt<span style='color:#308080; '>)</span><span style='color:#406080; '>;</span>
<span style='color:#406080; '>}</span>
<span style='color:#406080; '>}</span>
</div>
 
=== Assignment 3 ===
 
==== Problem Overview ====
An N-body simulation is a simulation of a dynamical system of particles, usually under the influence of physical forces, such as gravity. In cosmology, they are used to study processes of non-linear structure formation such as the process of forming galaxy filaments and galaxy halos from dark matter in physical cosmology. Direct N-body simulations are used to study the dynamical evolution of star clusters.
 
To be able to successfully have an N-body simulation, a program must go through each body, and add the forces of each other body that is affecting it to update where its position would be in the simulation. Due to this, the algorithm that is used to do these calculations has a time complexity of O(n^2). Having the time increase exponentially as n increases linearly makes the simulation rather slow, and thus a perfect candidate for parallelization.
 
==== Baseline ====
The following profiles were made under the following compiler and computer settings:
 
<pre>nvcc main.cpp timer.cpp sim\simbody.cu sim\simulation.cu -DWIN32 -O3</pre>
 
* i5 2500K @ 4.5Ghz
* Nvidia GTX 560Ti
* Raw computations, no graphics drawn to the screen for unbiased results.
* Random position, velocity and mass for each body.
* Brute force algorithm for calculating the forces (O(n^2)).
 
==== Initial Profiling ====
 
Initially, the serial version of this program took about 13 minutes to calculate 512 samples in a 5000-body simulation. Even with the use of Steaming SIMD Extensions, the program took about 7 minutes to do the same test.
 
==== Parallelization ====
 
===== Basic Parallelization =====
 
* Turned old serial code where the program bottlenecked to into two separate kernels
 
===== Optimized Parallelization =====
 
* Changed the launch configuration for the kernels so there were no wasted threads (based on devices compute capabilities)
* Prefetched values that don’t change throughout the loops
* Did computations in the kernel to reduce function overhead
* Used constant memory for the gravitation constant
 
==== Profiles ====
 
===== Profile #1 =====
 
[[File:cosmosis_assn3_p1_1.png|border]]
 
 
[[File:cosmosis_assn3_p1_2.png|border]]
 
To be able to see the difference between the pre and post optimized code, this graph does not include the serial cpu timings.
 
===== Profile #2 =====
Our second profile again consists of running simulations for 240 seconds to determine how many samples we achieve per second, and how many total samples we end up with after four minutes.
 
[[File:cosmosis_assn3_p2_1.png|border]]
 
Optimized GPU after four minutes.
 
 
[[File:cosmosis_assn3_p2_2.png|border]]
 
Naive GPU Samples after four minutes.
 
 
Comparing our results from the previous GPU implementation, we managed to achieve a total of 188072 samples compared to 88707. Roughly a 112.015 % increase in the number of samples completed in four minutes. Compared with our CPU code, the optimized GPU code is 1421.741% faster.
 
==== Test Suite ====
 
[[File:cosmosis_assn3_test.png|border]]
 
During the initial stages of our optimizations, we noticed that incorrect data started showing up after some changes. In order to ensure that even after our optimizations the data was still correct we had to develop a comprehensive test suite. The test suite goes through multiple tests and compares host values (assumed 100% correct) to the device values. These values are compared using their final position after a number of samples. The test suite allows for 1.0 difference in values to compensate for floating-point errors.
 
==== Conclusions ====
 
Through the use of CUDA, we managed to achieve a total of 4229.33% speedup in time from serial CPU to the final optimized GPU. We used many basic techniques to achieve a speedup of 35.4% from the pre-optimized code, to the post-optimized code. There were several different parallelization techniques that we did not manage to get to work with our program that could have sped it up even further. One such thing was shared memory.
 
Our kernels accessed the same bodies for the calculations so we tried to implement shared memory so that threads in a current block can access them faster. It worked when n bodies was less than 1755 for graphics cards with a compute capability of 2.x. This is due to the fact that a body took up 28 bytes in memory, hence why 1755 bodies would not work because it took up 49,140 bytes (greater than the max shared memory a 2.x graphics card can hold: 48K). There was a roundabout way of feeding the kernel chunks of bodies at a time that only worked on some occasions, so we ended up scrapping it.
 
We initially intended on using the fast-math library provided by CUDA. At first our results were marginally faster than our previous code. Though after some optimizations we discovered that our code actually performed better than the fast-math library. With fast-math, it took 0.451889 seconds to process 1000 bodies for 512 samples, conversely without fast-math we got 0.409581 seconds, which is a considerable improvement.
 
==== Optimized Code ====
 
<div style='color:#000020;background:#f6f8ff;'>
<span style='color:#200080; font-weight:bold; '>void</span> __global__ SimCalc<span style='color:#308080; '>(</span>BodyArray a<span style='color:#308080; '>)</span>
<span style='color:#406080; '>{</span>
int_fast32_t idx <span style='color:#308080; '>=</span> blockIdx<span style='color:#308080; '>.</span>x <span style='color:#308080; '>*</span> blockDim<span style='color:#308080; '>.</span>x <span style='color:#308080; '>+</span> threadIdx<span style='color:#308080; '>.</span>x<span style='color:#406080; '>;</span>
<span style='color:#200080; font-weight:bold; '>if</span> <span style='color:#308080; '>(</span>idx <span style='color:#308080; '>&lt;</span> a<span style='color:#308080; '>.</span>size<span style='color:#308080; '>)</span> <span style='color:#406080; '>{</span>
<span style='color:#200080; font-weight:bold; '>const</span> _T G <span style='color:#308080; '>=</span> <span style='color:#008000; '>6.67384</span><span style='color:#006600; '>f</span> <span style='color:#308080; '>*</span> <span style='color:#003060; '>pow</span><span style='color:#308080; '>(</span><span style='color:#008000; '>10.0</span><span style='color:#006600; '>f</span><span style='color:#308080; '>,</span> <span style='color:#308080; '>-</span><span style='color:#008000; '>11.0</span><span style='color:#006600; '>f</span><span style='color:#308080; '>)</span><span style='color:#406080; '>;</span>
<span style='color:#595979; '>//precompute positions at index</span>
<span style='color:#200080; font-weight:bold; '>const</span> _T px <span style='color:#308080; '>=</span> a<span style='color:#308080; '>.</span>array<span style='color:#308080; '>[</span>idx<span style='color:#308080; '>]</span><span style='color:#308080; '>.</span>Position<span style='color:#308080; '>.</span>x<span style='color:#406080; '>;</span>
<span style='color:#200080; font-weight:bold; '>const</span> _T py <span style='color:#308080; '>=</span> a<span style='color:#308080; '>.</span>array<span style='color:#308080; '>[</span>idx<span style='color:#308080; '>]</span><span style='color:#308080; '>.</span>Position<span style='color:#308080; '>.</span>y<span style='color:#406080; '>;</span>
<span style='color:#595979; '>//mass at the index</span>
<span style='color:#200080; font-weight:bold; '>const</span> _T M_idx <span style='color:#308080; '>=</span> G<span style='color:#308080; '>*</span>a<span style='color:#308080; '>.</span>array<span style='color:#308080; '>[</span>idx<span style='color:#308080; '>]</span><span style='color:#308080; '>.</span>Mass<span style='color:#406080; '>;</span>
a<span style='color:#308080; '>.</span>array<span style='color:#308080; '>[</span>idx<span style='color:#308080; '>]</span><span style='color:#308080; '>.</span>Force <span style='color:#308080; '>=</span> vec2_t<span style='color:#308080; '>(</span><span style='color:#308080; '>)</span><span style='color:#406080; '>;</span>
<span style='color:#200080; font-weight:bold; '>for</span> <span style='color:#308080; '>(</span>int_fast32_t j<span style='color:#308080; '>(</span><span style='color:#008c00; '>0</span><span style='color:#308080; '>)</span><span style='color:#406080; '>;</span> j <span style='color:#308080; '>!</span><span style='color:#308080; '>=</span> a<span style='color:#308080; '>.</span>size<span style='color:#406080; '>;</span> <span style='color:#308080; '>+</span><span style='color:#308080; '>+</span>j<span style='color:#308080; '>)</span> <span style='color:#406080; '>{</span>
<span style='color:#200080; font-weight:bold; '>if</span> <span style='color:#308080; '>(</span>idx <span style='color:#308080; '>!</span><span style='color:#308080; '>=</span> j<span style='color:#308080; '>)</span> <span style='color:#406080; '>{</span>
_T dx <span style='color:#308080; '>=</span> a<span style='color:#308080; '>.</span>array<span style='color:#308080; '>[</span>j<span style='color:#308080; '>]</span><span style='color:#308080; '>.</span>Position<span style='color:#308080; '>.</span>x <span style='color:#308080; '>-</span> px<span style='color:#406080; '>;</span>
_T dy <span style='color:#308080; '>=</span> a<span style='color:#308080; '>.</span>array<span style='color:#308080; '>[</span>j<span style='color:#308080; '>]</span><span style='color:#308080; '>.</span>Position<span style='color:#308080; '>.</span>y <span style='color:#308080; '>-</span> py<span style='color:#406080; '>;</span>
_T r <span style='color:#308080; '>=</span> <span style='color:#003060; '>sqrt</span><span style='color:#308080; '>(</span>dx<span style='color:#308080; '>*</span>dx <span style='color:#308080; '>+</span> dy<span style='color:#308080; '>*</span>dy<span style='color:#308080; '>)</span><span style='color:#406080; '>;</span>
_T F <span style='color:#308080; '>=</span> <span style='color:#308080; '>(</span>M_idx<span style='color:#308080; '>*</span>a<span style='color:#308080; '>.</span>array<span style='color:#308080; '>[</span>j<span style='color:#308080; '>]</span><span style='color:#308080; '>.</span>Mass<span style='color:#308080; '>)</span><span style='color:#308080; '>/</span><span style='color:#308080; '>(</span>r<span style='color:#308080; '>*</span>r<span style='color:#308080; '>)</span><span style='color:#406080; '>;</span>
a<span style='color:#308080; '>.</span>array<span style='color:#308080; '>[</span>idx<span style='color:#308080; '>]</span><span style='color:#308080; '>.</span>Force<span style='color:#308080; '>.</span>x <span style='color:#308080; '>+</span><span style='color:#308080; '>=</span> F <span style='color:#308080; '>*</span> <span style='color:#308080; '>(</span>dx <span style='color:#308080; '>/</span> r<span style='color:#308080; '>)</span><span style='color:#406080; '>;</span>
a<span style='color:#308080; '>.</span>array<span style='color:#308080; '>[</span>idx<span style='color:#308080; '>]</span><span style='color:#308080; '>.</span>Force<span style='color:#308080; '>.</span>y <span style='color:#308080; '>+</span><span style='color:#308080; '>=</span> F <span style='color:#308080; '>*</span> <span style='color:#308080; '>(</span>dy <span style='color:#308080; '>/</span> r<span style='color:#308080; '>)</span><span style='color:#406080; '>;</span>
<span style='color:#406080; '>}</span>
<span style='color:#406080; '>}</span>
<span style='color:#406080; '>}</span>
 
<span style='color:#200080; font-weight:bold; '>void</span> __global__ SimTick<span style='color:#308080; '>(</span>BodyArray a<span style='color:#308080; '>,</span> _T dt<span style='color:#308080; '>)</span>
<span style='color:#406080; '>{</span>
<span style='color:#200080; font-weight:bold; '>int</span> idx <span style='color:#308080; '>=</span> blockIdx<span style='color:#308080; '>.</span>x <span style='color:#308080; '>*</span> blockDim<span style='color:#308080; '>.</span>x <span style='color:#308080; '>+</span> threadIdx<span style='color:#308080; '>.</span>x<span style='color:#406080; '>;</span>
<span style='color:#200080; font-weight:bold; '>if</span> <span style='color:#308080; '>(</span>idx <span style='color:#308080; '>&lt;</span> a<span style='color:#308080; '>.</span>size<span style='color:#308080; '>)</span>
<span style='color:#406080; '>{</span>
_T mass <span style='color:#308080; '>=</span> a<span style='color:#308080; '>.</span>array<span style='color:#308080; '>[</span>idx<span style='color:#308080; '>]</span><span style='color:#308080; '>.</span>Mass<span style='color:#406080; '>;</span>
a<span style='color:#308080; '>.</span>array<span style='color:#308080; '>[</span>idx<span style='color:#308080; '>]</span><span style='color:#308080; '>.</span>Velocity<span style='color:#308080; '>.</span>x <span style='color:#308080; '>+</span><span style='color:#308080; '>=</span> dt <span style='color:#308080; '>*</span> <span style='color:#308080; '>(</span>a<span style='color:#308080; '>.</span>array<span style='color:#308080; '>[</span>idx<span style='color:#308080; '>]</span><span style='color:#308080; '>.</span>Force<span style='color:#308080; '>.</span>x <span style='color:#308080; '>/</span> mass<span style='color:#308080; '>)</span><span style='color:#406080; '>;</span>
a<span style='color:#308080; '>.</span>array<span style='color:#308080; '>[</span>idx<span style='color:#308080; '>]</span><span style='color:#308080; '>.</span>Velocity<span style='color:#308080; '>.</span>y <span style='color:#308080; '>+</span><span style='color:#308080; '>=</span> dt <span style='color:#308080; '>*</span> <span style='color:#308080; '>(</span>a<span style='color:#308080; '>.</span>array<span style='color:#308080; '>[</span>idx<span style='color:#308080; '>]</span><span style='color:#308080; '>.</span>Force<span style='color:#308080; '>.</span>y <span style='color:#308080; '>/</span> mass<span style='color:#308080; '>)</span><span style='color:#406080; '>;</span>
a<span style='color:#308080; '>.</span>array<span style='color:#308080; '>[</span>idx<span style='color:#308080; '>]</span><span style='color:#308080; '>.</span>Position<span style='color:#308080; '>.</span>x <span style='color:#308080; '>+</span><span style='color:#308080; '>=</span> dt <span style='color:#308080; '>*</span> a<span style='color:#308080; '>.</span>array<span style='color:#308080; '>[</span>idx<span style='color:#308080; '>]</span><span style='color:#308080; '>.</span>Velocity<span style='color:#308080; '>.</span>x<span style='color:#406080; '>;</span>
a<span style='color:#308080; '>.</span>array<span style='color:#308080; '>[</span>idx<span style='color:#308080; '>]</span><span style='color:#308080; '>.</span>Position<span style='color:#308080; '>.</span>y <span style='color:#308080; '>+</span><span style='color:#308080; '>=</span> dt <span style='color:#308080; '>*</span> a<span style='color:#308080; '>.</span>array<span style='color:#308080; '>[</span>idx<span style='color:#308080; '>]</span><span style='color:#308080; '>.</span>Velocity<span style='color:#308080; '>.</span>y<span style='color:#406080; '>;</span>
<span style='color:#406080; '>}</span>
<span style='color:#406080; '>}</span>
</div>
 
==== Launch Control ====
 
We used the following calculations to determine the the number of threads and blocks to launch with:
 
<div style='color:#000020;background:#f6f8ff;'>
numThreads_ <span style='color:#308080; '>=</span> prop<span style='color:#308080; '>.</span>maxThreadsPerMultiProcessor <span style='color:#308080; '>/</span> maxBlocks<span style='color:#406080; '>;</span>
numBlocks_ <span style='color:#308080; '>=</span> <span style='color:#308080; '>(</span>bodies_<span style='color:#308080; '>.</span>size<span style='color:#308080; '>(</span><span style='color:#308080; '>)</span> <span style='color:#308080; '>+</span> numThreads_ <span style='color:#308080; '>-</span> <span style='color:#008c00; '>1</span><span style='color:#308080; '>)</span> <span style='color:#308080; '>/</span> numThreads_<span style='color:#406080; '>;</span>
numThreads_ <span style='color:#308080; '>=</span> <span style='color:#308080; '>(</span>numThreads_ <span style='color:#308080; '>+</span> <span style='color:#008c00; '>1</span><span style='color:#308080; '>)</span> <span style='color:#308080; '>&amp;</span> <span style='color:#308080; '>~</span><span style='color:#008c00; '>1</span><span style='color:#406080; '>;</span>
</div>
 
==== Dynamic Shared Memory (not implemented) ====
 
This is the roundabout way we thought of, of how to send in chunks to the kernel so that the kernel can handle shared memory size of no greater than the max shared memory size of the GPU:
<div style='color:#000000;background:#ffffff;'>
CHUNKSIZE <span style='color:#808030; '>=</span> <span style='color:#008c00; '>512</span><span style='color:#800080; '>;</span>
shared_ <span style='color:#808030; '>=</span> CHUNKSIZE <span style='color:#808030; '>*</span> <span style='color:#800000; font-weight:bold; '>sizeof</span><span style='color:#808030; '>(</span>SimBody<span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
<span style='color:#800000; font-weight:bold; '>while</span> <span style='color:#808030; '>(</span>chunks <span style='color:#808030; '>></span> <span style='color:#008c00; '>0</span><span style='color:#808030; '>)</span>
<span style='color:#800080; '>{</span>
BodyArray ba <span style='color:#808030; '>=</span> <span style='color:#800080; '>{</span> <span style='color:#808030; '>&amp;</span>arr<span style='color:#808030; '>.</span><span style='color:#603000; '>array</span><span style='color:#808030; '>[</span>index<span style='color:#808030; '>]</span><span style='color:#808030; '>,</span> CHUNKSIZE <span style='color:#800080; '>}</span><span style='color:#800080; '>;</span>
SimCalc <span style='color:#808030; '>&lt;</span><span style='color:#808030; '>&lt;</span><span style='color:#808030; '>&lt;</span> numBlocks_<span style='color:#808030; '>,</span> numThreads_<span style='color:#808030; '>,</span> shared_ <span style='color:#808030; '>></span><span style='color:#808030; '>></span><span style='color:#808030; '>></span><span style='color:#808030; '>(</span>ba<span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
cudaThreadSynchronize<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
SimTick <span style='color:#808030; '>&lt;</span><span style='color:#808030; '>&lt;</span><span style='color:#808030; '>&lt;</span> numBlocks_<span style='color:#808030; '>,</span> numThreads_<span style='color:#808030; '>,</span> shared_ <span style='color:#808030; '>></span><span style='color:#808030; '>></span><span style='color:#808030; '>></span><span style='color:#808030; '>(</span>ba<span style='color:#808030; '>,</span> timeStep<span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
cudaThreadSynchronize<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
index <span style='color:#808030; '>+</span><span style='color:#808030; '>=</span> CHUNKSIZE<span style='color:#800080; '>;</span>
<span style='color:#808030; '>-</span><span style='color:#808030; '>-</span>chunks<span style='color:#800080; '>;</span>
<span style='color:#800080; '>}</span>
chunks <span style='color:#808030; '>=</span> arr<span style='color:#808030; '>.</span>size <span style='color:#808030; '>/</span> CHUNKSIZE <span style='color:#808030; '>+</span> <span style='color:#008c00; '>1</span><span style='color:#800080; '>;</span>
index <span style='color:#808030; '>=</span> <span style='color:#008c00; '>0</span><span style='color:#800080; '>;</span>
</div>
It handles calculations in chunks so that the kernel can do calculations on body sizes of more than 1175 for devices with compute capabilities of 3.x.
 
Here is what the shared memory kernels would look like (not implemented because not correct):
<div style='color:#000000;background:#ffffff;'>
<span style='color:#800000; font-weight:bold; '>void</span> __global__ SimCalc<span style='color:#808030; '>(</span>BodyArray a<span style='color:#808030; '>)</span>
<span style='color:#800080; '>{</span>
int_fast32_t idx <span style='color:#808030; '>=</span> blockIdx<span style='color:#808030; '>.</span>x <span style='color:#808030; '>*</span> blockDim<span style='color:#808030; '>.</span>x <span style='color:#808030; '>+</span> threadIdx<span style='color:#808030; '>.</span>x<span style='color:#800080; '>;</span>
<span style='color:#800000; font-weight:bold; '>int</span> tid <span style='color:#808030; '>=</span> threadIdx<span style='color:#808030; '>.</span>x<span style='color:#800080; '>;</span>
<span style='color:#800000; font-weight:bold; '>extern</span> __shared__ SimBody sa<span style='color:#808030; '>[</span><span style='color:#808030; '>]</span><span style='color:#800080; '>;</span>
<span style='color:#800000; font-weight:bold; '>if</span> <span style='color:#808030; '>(</span>idx <span style='color:#808030; '>></span><span style='color:#808030; '>=</span> a<span style='color:#808030; '>.</span>size<span style='color:#808030; '>)</span>
<span style='color:#800000; font-weight:bold; '>return</span><span style='color:#800080; '>;</span>
sa<span style='color:#808030; '>[</span>tid<span style='color:#808030; '>]</span> <span style='color:#808030; '>=</span> a<span style='color:#808030; '>.</span><span style='color:#603000; '>array</span><span style='color:#808030; '>[</span>idx<span style='color:#808030; '>]</span><span style='color:#800080; '>;</span>
__syncthreads<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
<span style='color:#800000; font-weight:bold; '>const</span> _T G <span style='color:#808030; '>=</span> <span style='color:#008000; '>6.67384</span><span style='color:#006600; '>f</span> <span style='color:#808030; '>*</span> <span style='color:#603000; '>pow</span><span style='color:#808030; '>(</span><span style='color:#008000; '>10.0</span><span style='color:#006600; '>f</span><span style='color:#808030; '>,</span> <span style='color:#808030; '>-</span><span style='color:#008000; '>11.0</span><span style='color:#006600; '>f</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
<span style='color:#696969; '>//precompute positions at index</span>
<span style='color:#800000; font-weight:bold; '>const</span> _T px <span style='color:#808030; '>=</span> sa<span style='color:#808030; '>[</span>tid<span style='color:#808030; '>]</span><span style='color:#808030; '>.</span>Position<span style='color:#808030; '>.</span>x<span style='color:#800080; '>;</span>
<span style='color:#800000; font-weight:bold; '>const</span> _T py <span style='color:#808030; '>=</span> sa<span style='color:#808030; '>[</span>tid<span style='color:#808030; '>]</span><span style='color:#808030; '>.</span>Position<span style='color:#808030; '>.</span>y<span style='color:#800080; '>;</span>
<span style='color:#696969; '>//mass at the index</span>
<span style='color:#800000; font-weight:bold; '>const</span> _T M_idx <span style='color:#808030; '>=</span> G<span style='color:#808030; '>*</span>sa<span style='color:#808030; '>[</span>tid<span style='color:#808030; '>]</span><span style='color:#808030; '>.</span>Mass<span style='color:#800080; '>;</span>
sa<span style='color:#808030; '>[</span>tid<span style='color:#808030; '>]</span><span style='color:#808030; '>.</span>Force <span style='color:#808030; '>=</span> vec2_t<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
<span style='color:#800000; font-weight:bold; '>for</span> <span style='color:#808030; '>(</span>int_fast32_t j<span style='color:#808030; '>(</span><span style='color:#008c00; '>0</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span> j <span style='color:#808030; '>!</span><span style='color:#808030; '>=</span> a<span style='color:#808030; '>.</span>size<span style='color:#800080; '>;</span> <span style='color:#808030; '>+</span><span style='color:#808030; '>+</span>j<span style='color:#808030; '>)</span> <span style='color:#800080; '>{</span>
<span style='color:#800000; font-weight:bold; '>if</span> <span style='color:#808030; '>(</span>idx <span style='color:#808030; '>!</span><span style='color:#808030; '>=</span> j<span style='color:#808030; '>)</span> <span style='color:#800080; '>{</span>
_T dx <span style='color:#808030; '>=</span> a<span style='color:#808030; '>.</span><span style='color:#603000; '>array</span><span style='color:#808030; '>[</span>j<span style='color:#808030; '>]</span><span style='color:#808030; '>.</span>Position<span style='color:#808030; '>.</span>x <span style='color:#808030; '>-</span> px<span style='color:#800080; '>;</span>
_T dy <span style='color:#808030; '>=</span> a<span style='color:#808030; '>.</span><span style='color:#603000; '>array</span><span style='color:#808030; '>[</span>j<span style='color:#808030; '>]</span><span style='color:#808030; '>.</span>Position<span style='color:#808030; '>.</span>y <span style='color:#808030; '>-</span> py<span style='color:#800080; '>;</span>
_T r <span style='color:#808030; '>=</span> <span style='color:#603000; '>sqrt</span><span style='color:#808030; '>(</span>dx<span style='color:#808030; '>*</span>dx <span style='color:#808030; '>+</span> dy<span style='color:#808030; '>*</span>dy<span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
_T F <span style='color:#808030; '>=</span> <span style='color:#808030; '>(</span>M_idx<span style='color:#808030; '>*</span>a<span style='color:#808030; '>.</span><span style='color:#603000; '>array</span><span style='color:#808030; '>[</span>j<span style='color:#808030; '>]</span><span style='color:#808030; '>.</span>Mass<span style='color:#808030; '>)</span><span style='color:#808030; '>/</span><span style='color:#808030; '>(</span>r<span style='color:#808030; '>*</span>r<span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
sa<span style='color:#808030; '>[</span>tid<span style='color:#808030; '>]</span><span style='color:#808030; '>.</span>Force<span style='color:#808030; '>.</span>x <span style='color:#808030; '>+</span><span style='color:#808030; '>=</span> F <span style='color:#808030; '>*</span> <span style='color:#808030; '>(</span>dx <span style='color:#808030; '>/</span> r<span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
sa<span style='color:#808030; '>[</span>tid<span style='color:#808030; '>]</span><span style='color:#808030; '>.</span>Force<span style='color:#808030; '>.</span>y <span style='color:#808030; '>+</span><span style='color:#808030; '>=</span> F <span style='color:#808030; '>*</span> <span style='color:#808030; '>(</span>dy <span style='color:#808030; '>/</span> r<span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
<span style='color:#800080; '>}</span>
__syncthreads<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
<span style='color:#800080; '>}</span>
a<span style='color:#808030; '>.</span><span style='color:#603000; '>array</span><span style='color:#808030; '>[</span>idx<span style='color:#808030; '>]</span> <span style='color:#808030; '>=</span> sa<span style='color:#808030; '>[</span>tid<span style='color:#808030; '>]</span><span style='color:#800080; '>;</span>
<span style='color:#800080; '>}</span>
 
<span style='color:#800000; font-weight:bold; '>void</span> __global__ SimTick<span style='color:#808030; '>(</span>BodyArray a<span style='color:#808030; '>,</span> _T dt<span style='color:#808030; '>)</span>
<span style='color:#800080; '>{</span>
<span style='color:#800000; font-weight:bold; '>int</span> idx <span style='color:#808030; '>=</span> blockIdx<span style='color:#808030; '>.</span>x <span style='color:#808030; '>*</span> blockDim<span style='color:#808030; '>.</span>x <span style='color:#808030; '>+</span> threadIdx<span style='color:#808030; '>.</span>x<span style='color:#800080; '>;</span>
<span style='color:#800000; font-weight:bold; '>int</span> tid <span style='color:#808030; '>=</span> threadIdx<span style='color:#808030; '>.</span>x<span style='color:#800080; '>;</span>
<span style='color:#800000; font-weight:bold; '>extern</span> __shared__ SimBody sa<span style='color:#808030; '>[</span><span style='color:#808030; '>]</span><span style='color:#800080; '>;</span>
<span style='color:#800000; font-weight:bold; '>if</span> <span style='color:#808030; '>(</span>idx <span style='color:#808030; '>></span><span style='color:#808030; '>=</span> a<span style='color:#808030; '>.</span>size<span style='color:#808030; '>)</span>
<span style='color:#800000; font-weight:bold; '>return</span><span style='color:#800080; '>;</span>
sa<span style='color:#808030; '>[</span>tid<span style='color:#808030; '>]</span> <span style='color:#808030; '>=</span> a<span style='color:#808030; '>.</span><span style='color:#603000; '>array</span><span style='color:#808030; '>[</span>idx<span style='color:#808030; '>]</span><span style='color:#800080; '>;</span>
__syncthreads<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
_T mass <span style='color:#808030; '>=</span> sa<span style='color:#808030; '>[</span>tid<span style='color:#808030; '>]</span><span style='color:#808030; '>.</span>Mass<span style='color:#800080; '>;</span>
sa<span style='color:#808030; '>[</span>tid<span style='color:#808030; '>]</span><span style='color:#808030; '>.</span>Velocity<span style='color:#808030; '>.</span>x <span style='color:#808030; '>+</span><span style='color:#808030; '>=</span> dt <span style='color:#808030; '>*</span> <span style='color:#808030; '>(</span>sa<span style='color:#808030; '>[</span>tid<span style='color:#808030; '>]</span><span style='color:#808030; '>.</span>Force<span style='color:#808030; '>.</span>x <span style='color:#808030; '>/</span> mass<span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
sa<span style='color:#808030; '>[</span>tid<span style='color:#808030; '>]</span><span style='color:#808030; '>.</span>Velocity<span style='color:#808030; '>.</span>y <span style='color:#808030; '>+</span><span style='color:#808030; '>=</span> dt <span style='color:#808030; '>*</span> <span style='color:#808030; '>(</span>sa<span style='color:#808030; '>[</span>tid<span style='color:#808030; '>]</span><span style='color:#808030; '>.</span>Force<span style='color:#808030; '>.</span>y <span style='color:#808030; '>/</span> mass<span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
sa<span style='color:#808030; '>[</span>tid<span style='color:#808030; '>]</span><span style='color:#808030; '>.</span>Position<span style='color:#808030; '>.</span>x <span style='color:#808030; '>+</span><span style='color:#808030; '>=</span> dt <span style='color:#808030; '>*</span> sa<span style='color:#808030; '>[</span>tid<span style='color:#808030; '>]</span><span style='color:#808030; '>.</span>Velocity<span style='color:#808030; '>.</span>x<span style='color:#800080; '>;</span>
sa<span style='color:#808030; '>[</span>tid<span style='color:#808030; '>]</span><span style='color:#808030; '>.</span>Position<span style='color:#808030; '>.</span>y <span style='color:#808030; '>+</span><span style='color:#808030; '>=</span> dt <span style='color:#808030; '>*</span> sa<span style='color:#808030; '>[</span>tid<span style='color:#808030; '>]</span><span style='color:#808030; '>.</span>Velocity<span style='color:#808030; '>.</span>y<span style='color:#800080; '>;</span>
__syncthreads<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
a<span style='color:#808030; '>.</span><span style='color:#603000; '>array</span><span style='color:#808030; '>[</span>idx<span style='color:#808030; '>]</span> <span style='color:#808030; '>=</span> sa<span style='color:#808030; '>[</span>tid<span style='color:#808030; '>]</span><span style='color:#800080; '>;</span>
<span style='color:#800080; '>}</span>
</div>
1
edit

Navigation menu