We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
IndexProgramming Questions & HelpPrograms › Multithread draw and millions of particles (2D)
Page Index Toggle Pages: 1
Multithread draw and millions of particles (2D) (Read 3368 times)
Multithread draw and millions of particles (2D)
Jun 12th, 2008, 5:48am
 
Friendly greetings !

I discovered "processing" yesterday and i already have tons of projects planned. wonderfull stuff here !

As a start projects, i heavily modified this :
http://www.openprocessing.org/visuals/?visualID=279

Cleaned most of the stuff (removed stalker, color change, etc...)

now i have only blue particle, red particle, N shared negactor, N red attractor, N blue attractor, N shared attractor.

i removed a lot of stuff to save memory too, and save cpu cycle.
I'm running millions of particles in a large window and a lot of negactor.

It's...well... slow Smiley

Fortunally, i have a quadcore cpu.
Infortunally, i'm not sure how to multithread that stuff.

i found some topic about multithreading in processing :
http://www.shiffman.net/teaching/a2z/threads/
http://processing.org/discourse/yabb_beta/YaBB.cgi?board=Integrate;action=display;num=1204990614

i have 5 classes :
the main
the attractor class
the force class
the particle class
the vector3D class

in main :
"setup" initialise some stuff.
"draw" is the main loop

in "draw" i have a few "for" loop, calling : particle[j].step();  
the drawing (a simple point(x,y)) is done in the particle class.


My idea is to create 4 threads and each thread have it's own millions of particle to manage. (particles are totally independant, they know need to know where are the other particles, they only need to know where are the attractor and negactor).

And i'm not sure how to do that.
Obiviously, i can't create a thread for each "step" call. (or it will (try to) create a few millions of threads).

I think i'll have to rebuild everything from scratch.
It's not a big project, but i' s*ck at OOP.

do you have an idea about "how i should implement the multithreading for many millions of particles, all doing exactly the same stuff and totally independant to eachothers ?"

I'll post the sourcecode asap, it will probably help you ton understand my problems Wink

thank you, and sorry for my english and my confused post.
Re: Multithread draw and millions of particles (2D
Reply #1 - Jun 12th, 2008, 5:52am
 
here it is : http://www.electrosphere.fr/java-source/
Re: Multithread draw and millions of particles (2D
Reply #2 - Jun 12th, 2008, 9:53am
 
Before running for a headache with multithreading, code optimization is a good idea. For example, stroke(color(c)); point (x,y); is a lot slower than directly accessing the pixels array : pixels[y*width+x] = c;.

Then, be aware that your threads are going to loop independently of your main draw() loop, which means, at their own speed. It's not like you could assign one particle per core and get 4 particles treated in only one cpu cycle.
Re: Multithread draw and millions of particles (2D
Reply #3 - Jun 12th, 2008, 10:10am
 
Thx for the info, i'll change that.
(i need a profiler ... but never used eclipse yet :/ )

yes, it won't be synchronous, and it's not a problem *at all*
Now... if i remember correctly, each thread will have it's own memory, and so it's own pixel[] array, right ? Updating this array from each core... won't update the display... will it ?

Maybe i should rewrite everything in a single class... that's confusing me.

Thx for the info Wink


Edit : mm... i have a problem.
x and y are float.
and if i write : pixels[(int)(y*width+x)] = color(c);
the result is totally false.

if i replace float with int, the simulation quality is really poor Sad
Re: Multithread draw and millions of particles (2D
Reply #4 - Jun 12th, 2008, 10:38am
 
You get get threads to run separately, but wait when they reach a certain point until told to resume.

I think the best approach would be to split your particles into 4 groups, and have 4 "particleGroup" classes that are threaded. Each particleGroup will also need a copy of all the attractors (assuming these are static) so they don't have to be accessing shared objects.

Each particleGroup runs through it's set of particles updating their positions etc, and then once all the maths is done, enters a wait state.

The main draw thread waits for all 4 groups to get to the wait state, draws all the particles, then tells them to go off calculating again whilst it handles actually swapping buffers etc.
Re: Multithread draw and millions of particles (2D
Reply #5 - Jun 12th, 2008, 11:21am
 
Well...
i understood that it's a good idea to have 4 group (one per core) of particles... and don't understand any single words your explanation. (other than the thread should wait when done)

BUT ... I found an old "Java 2 Ed 1999" book hidden behind some (interesting) Perl book with a chapter about Threads (50 pages). I'll read it and see if it help.

Maybe i should buy one of thoses shiny processing book too Wink
Re: Multithread draw and millions of particles (2D
Reply #6 - Jun 12th, 2008, 1:03pm
 
Well... i keep the point()
but to avoid this bottleneck i try another kind of simulation, same kind of stuff, but with less particle (20k instead of 2M) and more computation per particles.

I still want to multithread that Wink
I'll post another code when cleaned (did a lot of cleaning and optimisation)

Re: Multithread draw and millions of particles (2D
Reply #7 - Jun 12th, 2008, 7:05pm
 
Quote:
x and y are float. and if i write : pixels[(int)(y*width+x)] = color(c);
the result is totally false.

what wrong result do you get? that is the correct syntax, though. haven't you forgotten to call loadPixels(); before adressing the pixels array and updatePixels(); after setting the pixels 'manually'?

Quote:
i understood that it's a good idea to have 4 group (one per core) of particles...

it's a good idea to split your particles in groups. but is there a reason to believe that each thread will be treated by a different core? your cpu has a lot of other things to handle too : os, background services, jvm, etc...
Re: Multithread draw and millions of particles (2D
Reply #8 - Jun 13th, 2008, 12:06pm
 
update :

i rewrote the app, added some multithreading and found no performance increase. So i'm currently rewriting the whole stuff again, using eclipse. i just finished to install the profiler. i'll keep you updated. thx again for your help Wink
Re: Multithread draw and millions of particles (2D
Reply #9 - Jun 14th, 2008, 12:49am
 
Hi Laura, I asked the same question a while ago, and managed to get the multithreaded thing working quite well... (my original post here
http://processing.org/discourse/yabb_beta/YaBB.cgi?board=Syntax;action=display;num=1211296943 )

unfortunately in my case I needed very strong communication and synchronization between my threads so it got a bit complicated and I haven't had a chance to solve it yet.

In a nutshell, there are two ways of creating a multithreaded application. Having a class that extends the Thread class; or a class that implements the Runnable class and later link it up to an instance of a Thread. Either way, you give the class a 'run' method, and put some code in an infinite loop. That code in the infinite loop runs in its own thread (and all the functions it calls). All the memory, variables etc. it can access is shared in your application. So it can share data very easily with the main thread, and/or other threads in your app (which is the whole point really). This is the article that gave me the crash course on how it all works (which has some info on how it shouldn't just be any old infinite loop but should ideally check for a few messages, and sleep etc.)
http://www.javaworld.com/javaworld/jw-04-1996/jw-04-threads.html

So you really wanna create a Particle System class that manages a bunch of particles, and it should either extend Thread or implement Runnable, and then create 4 instances of that class with a million particles in each. The 'run' function of that class cycles through all of its own particles and updates them.

Of course having as optimum as possible code is always going to be always very important... especially if you intend to run a few million particles on each core! But if you write the multithreading properly, I can't see how it cannot be faster on a quadcore as opposed to a singlecore (unless you have the code on one core relying on the data from the code on the other core ... which is what i had :S ) - it could just be that the actual bottleneck is the drawing, (trying making your update function incredibly simple, and see if its still slow).

P.S. remember that the thread operates at an independent frame rate to your main application, and its the sleep value that determines it!
Re: Multithread draw and millions of particles (2D
Reply #10 - Jun 14th, 2008, 8:48am
 
To be able to use the profiler and debugger, i worked directly on the gereated java file, using eclipse.
here is the source code : http://www.electrosphere.fr/java-source/PartNG_7.java

If it can be done in eclipse, it can be done in processing IDE, right ? Wink

The application was simplified (a lot) to be able to easily keep track of bugs. (which isn't easy in multithread).

i coded for 20h in a row yesterday, had to learn everything about thread in java, and tried many many possible solution.
i finally found the the safest and simpliest one using the latest java version.

i use : Executors.newFixedThreadPool(4);
it will provide the hability to reuse thread instead of creating new thread at every frame.

then i created a "Callable" class (called "myThread" ...).
The problem was :
- how do i give arguments to a thread.
- how do i wait all 4 threads before continuing a new draw loop.
- how do i retrieve the result.

i still use the "point(x,y)" method beacuse it's handy and because i'm planning to do that in 3D do. And the pixel[] tricks won't work in 3D Wink

The "point(x,y)" is absolutly not threadsafe. So i had to do all the drawing in a single thread, once the 4 thread finished the processing. And so... i had to find a way to do something like :
- main loop : i'm waiting for you guys.
- thread 1 : i finished my work, here is the list of point to draw.
- thread 2,3,4 : yeah, me too. here is my list.
- main loop : thx. i'll draw the stuff myself.

Using Callable, the thread can return anything.
i choosed to return an ArrayList<Vector3D>.

To be able the retrieve a value (or a list of value, or whatever), i had to use a "Future" ("FutureTask" can be used to, afaik).

Future is a class providing the ability to pause, cancel, request a return value, and some shiny stuff from thread. (and also throw an exception when something went wrong).

it's all in the new : java.util.concurrent.* package.

anyway, in my draw loop, i create the thread :
 myThread thread1 = new myThread(particles, NUM_PARTICLES, cRed);
 myThread thread2 = new myThread(particles2, NUM_PARTICLES, cBlue);
 myThread thread3 = new myThread(particles3, NUM_PARTICLES, cRed);
 myThread thread4 = new myThread(particles4, NUM_PARTICLES, cBlue);

and tell them to start, the executor return the "Future" handle.

 Future future1 = executor.submit(thread1);
 Future future2 = executor.submit(thread2);
 Future future3 = executor.submit(thread3);
 Future future4 = executor.submit(thread4);

while they work, i create my 4 ArrayList<Vector3D> to store the result in the main thread.

 ArrayList<Vector3D> myResult1 = new ArrayList<Vector3D>(NUM_PARTICLES);
 ArrayList<Vector3D> myResult2 = new ArrayList<Vector3D>(NUM_PARTICLES);
 ArrayList<Vector3D> myResult3 = new ArrayList<Vector3D>(NUM_PARTICLES);
 ArrayList<Vector3D> myResult4 = new ArrayList<Vector3D>(NUM_PARTICLES);


now i'm waiting for the thread. the Future.get(); is a blocking operation (there is some non-blocking one, but i wanted a blocking one).

 try
 {
 myResult1 = (ArrayList<Vector3D>)future1.get();
 myResult2 = (ArrayList<Vector3D>)future2.get();
 myResult3 = (ArrayList<Vector3D>)future3.get();
 myResult4 = (ArrayList<Vector3D>)future4.get();

 }
 catch (Exception e) {
 System.err.println (e);
// add some exception handling stuff here.
 }

now i have my fully completed result and the thread are waiting for new stuff.

i draw the result :

  for(int i = 0; i < NUM_PARTICLES; i++)
 {
 stroke(cBlue);
 point(myResult1.get(i).x, myResult1.get(i).y);
 point(myResult2.get(i).x, myResult2.get(i).y);
 stroke(cRed);
 point(myResult3.get(i).x, myResult3.get(i).y);
 point(myResult4.get(i).x, myResult4.get(i).y);

 }

and i'm ready for a new loop.
Job done.


it need some kind of improvment.
But, right now, i'm 100% sure that it's all threadsafe. No fancy memory-inconsistancy, dead-lock, or other annoying problems.

i used a simple ArrayList<T> but there is a kind ThreadList specialy created for thrreadsafe operation in the concurrent package. I didn't used it because it wasn't required here. (it's all synchronous and each thread are warranted to have their own Array and nobody trying to read/write their array while working on it.).

a good optimisation could be to create a non-blocking "drawing thread", so the thread could start working on a new set of value while everything is drawn, instead of waiting for the drawing to finish.

Another optimisation is about memory usage.
But i'm not sure how to safely save some memory without creating some kinds of weird problem, or having to use mutex.

I think it could be nice to create a processing thread library. Using Executor and Future.
Re: Multithread draw and millions of particles (2D)
Reply #11 - Jun 21st, 2009, 7:25pm
 
Great idea !
This strategy of yours with executors works pretty well....
I used it to get some nice simulation to do higher particle counts,
by my experience it can get 10-20% faster on dualcore and up to 42% on quad core , becuase I still do drawing in single thread (but even that could be kind-of-fixed with drawing some particles just before all the particles are processed ....)

the whole code is too large to be posted here, but you can get it at
live example at openprocessing  Wink  -

openprocessing.org/visuals/?visualID=2603

(sorry I cannot yet post links  Huh )

regards
PV
Page Index Toggle Pages: 1