Speeding up particle simulation

Click For Summary
The discussion centers on optimizing a particle simulation program that currently operates with a complexity of O(n(n-1)/2), making it too slow for real-time interaction. The user is exploring methods to reduce this complexity to O(n) by focusing on near-neighbor interactions and is considering using spatial partitioning structures like octrees or quadtrees. However, maintaining these structures is challenging due to the dynamic movement of particles.Suggestions for optimization include minimizing expensive mathematical operations, such as divisions, and utilizing vector math libraries for potential performance gains through threading and SIMD instructions. The user is advised to accumulate forces before updating particle positions and to avoid unnecessary calculations, like square roots, in the inner loop. Implementing a distance limit to ignore distant particles is also recommended.The user has tested some optimizations and found mixed results, noting that replacing divisions with multiplications did not yield the expected performance improvement. They are now investigating K-D trees for efficient nearest neighbor searches, aiming for an O(n log(n)) solution.
fargoth
Messages
318
Reaction score
6
Hi, I've got a list of particles (where each particle has it's coordinates in space and velocity)
these particles can interact with each-other (f=\frac{a}{r^4}-\frac{b}{r^8})
(i'll add 6 - 12 soon too)
anyway, as it is now, the program has a complexity of O(\frac{n(n-1)}{2})
because every pair has to be calculated to get the force.

the problem is - its too slow for realtime simulation - and i want it to be interactive (changing the temperature, zooming in and out, etc.)

so, i started thinking about approximations i could do to make it work with O(n), and still get good results...
I think calculating the force for near neighbors is enough - but then i need a quick way to know who those neighbors are for a given particle (in less then O(n)).

I thought i'd use an octree (for 3D case) or quadtree (for 2D case), but i can't think of a way to maintain it - because the particles are always moving from place to place... i need to rebuild it each time...

I hope i was clear enough.. my question is - do you think my approach is the best one?
do you have any suggestion as to how to maintain the tree, or alternatively use a better approximation?
 
Technology news on Phys.org
don't forget to optimise the code as well as the algorithm, this way you can squeeze the most out of which ever algorithm you choose (algorithmic optimisation is more important in general though)

use a vector math library if possible as it might optimise to use threads and simd instruction

also try to reduce divisions and other expensive math operations, e.g. to calculate f:

var = 1 / r*r;
var = var * var;
f = a * var;
var = var * var;
f = f - b * var;

3 multiplications is faster than 2 calls to power functions and there is only one division, the other has been exchanged for 2 multiplications in essence...

you can optimise further by accumulating the force from all of the particles before moving each one, you can remove one of the multiplies if you use 1/r^4 - (b/a)/r^8 as well, then multiply the total force by a afterwards (calculate b/a once in a variable)

in the inner loop, don't take the square root of r if possible, since you probably use its square a lot, you might be able to get away with it.

another simple trick is to not count distant particles. you are calculating r in the inner loop, if you do this first you can early out if it is above some value, gives the same effect as rounding small values to zero.

if precision doesn't matter much then use only 32-bit floats for a minor performance gain.

hope this helps.
 
Jheriko said:
don't forget to optimise the code as well as the algorithm, this way you can squeeze the most out of which ever algorithm you choose (algorithmic optimisation is more important in general though)

use a vector math library if possible as it might optimise to use threads and simd instruction

also try to reduce divisions and other expensive math operations, e.g. to calculate f:

var = 1 / r*r;
var = var * var;
f = a * var;
var = var * var;
f = f - b * var;

3 multiplications is faster than 2 calls to power functions and there is only one division, the other has been exchanged for 2 multiplications in essence...

you can optimise further by accumulating the force from all of the particles before moving each one, you can remove one of the multiplies if you use 1/r^4 - (b/a)/r^8 as well, then multiply the total force by a afterwards (calculate b/a once in a variable)

in the inner loop, don't take the square root of r if possible, since you probably use its square a lot, you might be able to get away with it.

another simple trick is to not count distant particles. you are calculating r in the inner loop, if you do this first you can early out if it is above some value, gives the same effect as rounding small values to zero.

if precision doesn't matter much then use only 32-bit floats for a minor performance gain.

hope this helps.

thank you very much.
I will spare one division in the inner loop thanks to you..

(EDIT: after testing to see what impact it has on the speed i can tell you that using multiplications instead of divisions doesn't help - on the contrary - on my system it gave me 5% penalty... and sqrtf is VERY efficient, if i use it in the inner loop i only lose about 5% performance)

i'm already using the distance limit you've suggested - but when i cool the system down, and everything is squeezed to liquid or solid - the distance limit includes them all - i could make my distance limit change according to temperature, but i think using an efficient algorithm for finding nearest neighbors will get me better accuracy, and it might even be a better...

i'm looking into K-D trees now... see if i can use it to find nearest neighbors efficiently.
 
Last edited:
This is probably an order n problem- because there are no long range forces.

You only have to sum over interactions which are less than rmax apart. For instance- it might be that the simulation converges by summing over a sphere of ~100 particles around each target particle.

The problem is how to work out which particles are within the sphere. This can be done using neighbor lists.
 
las3rjock said:

thanks, I've gone over the text.
I knew I'm in the right direction.
(using the adaptive nearest neighbor approach to get O(n log(n)))
but I'm having trouble implementing it... and the paper doesn't talk about implementation...
oh well, i guess I'll have to tackle it some more =)
 
Learn If you want to write code for Python Machine learning, AI Statistics/data analysis Scientific research Web application servers Some microcontrollers JavaScript/Node JS/TypeScript Web sites Web application servers C# Games (Unity) Consumer applications (Windows) Business applications C++ Games (Unreal Engine) Operating systems, device drivers Microcontrollers/embedded systems Consumer applications (Linux) Some more tips: Do not learn C++ (or any other dialect of C) as a...

Similar threads

  • · Replies 19 ·
Replies
19
Views
4K
  • · Replies 1 ·
Replies
1
Views
4K
  • · Replies 14 ·
Replies
14
Views
4K
  • · Replies 12 ·
Replies
12
Views
3K
Replies
4
Views
1K
  • · Replies 7 ·
Replies
7
Views
3K
  • · Replies 2 ·
Replies
2
Views
3K
  • · Replies 1 ·
Replies
1
Views
759
  • · Replies 6 ·
Replies
6
Views
2K
  • · Replies 1 ·
Replies
1
Views
515