Page 2 of 4 FirstFirst 1234 LastLast
Results 11 to 20 of 35

Thread: Some gravity particles

  1. #11
    This is the only part where thread collisions can happen. It is possible that some force vectors are not added to movement, but is that likely?
    Code:
                movement.x:=movement.x+vec.x;
                movement.y:=movement.y+vec.y;
                movement.z:=movement.z+vec.z;
                star[j].movement.x:=star[j].movement.x-vec.x;
                star[j].movement.y:=star[j].movement.y-vec.y;
                star[j].movement.z:=star[j].movement.z-vec.z;
    Also the mainloop's part for threads is like:
    Code:
        i2:=count div 4;
        i3:=i2*2;
        i4:=i2*3;
        TPhysicsThread.Create(self, 0, i2-1);
        TPhysicsThread.Create(self, i2, i3-1);
        TPhysicsThread.Create(self, i3, i4-1);
        TPhysicsThread.Create(self, i4, count-2);
        while threads>0 do begin
          sleep(1); // It takes usually over 140ms, so sleep here is not unnecessary
          Application.ProcessMessages;
        end;
    ...
    constructor TPhysicsThread.Create(parent: TGame; const first, last: cardinal);
    ...
    Thread execute:
    ...
        for i:=FFirst to FLast do
          with star[i] do
            for j:=i+1 to count-1 do begin
    So it will not stop responding. I know it could be done better though, even so that fps wouldn't be affected. I also realize now that all the threads aren't getting equal workload at all. Especially the first thread gets biggest work, and 4th one the smallest.

    Win32-binaries and source code here: https://docs.google.com/file/d/0B7FI...it?usp=sharing
    Requires Lazarus and nxpascal to compile, possibly SVN version. All the required files are here:
    https://code.google.com/p/nxpascal/s...%2Ftrunk%2Fsrc
    Last edited by User137; 13-06-2013 at 10:07 PM.

  2. #12
    Quote Originally Posted by User137 View Post
    Also the mainloop's part for threads is like:
    Code:
        i2:=count div 4;
        i3:=i2*2;
        i4:=i2*3;
        TPhysicsThread.Create(self, 0, i2-1);
        TPhysicsThread.Create(self, i2, i3-1);
        TPhysicsThread.Create(self, i3, i4-1);
        TPhysicsThread.Create(self, i4, count-2);
        while threads>0 do begin
          sleep(1); // It takes usually over 140ms, so sleep here is not unnecessary
          Application.ProcessMessages;
        end;
    ...
    constructor TPhysicsThread.Create(parent: TGame; const first, last: cardinal);
    ...
    Thread execute:
    ...
        for i:=FFirst to FLast do
          with star[i] do
            for j:=i+1 to count-1 do begin
    So it will not stop responding. I know it could be done better though, even so that fps wouldn't be affected. I also realize now that all the threads aren't getting equal workload at all. Especially the first thread gets biggest work, and 4th one the smallest.
    First of all get that Application.ProcessMessages out of that loop. It is not good to call Application.Process messages to often. And the reason why your main thread has so much load is becouse of Application.ProcessMessavges. It is quite resource consuming call. And all that processing time that is used by Application.ProcessMessages is taken away from one of your other threads making everything slower. And since you sad that you only have dual core the impact on overal speed can be quite big.
    Wanna see how much Application.ProcessMessages affect your application. Start the simulation with setting sthat will cause low FPS, rotate the view and then pause the simulation. You will se that after you pause the simulation the overal view will quickly rotate to proper position while when being at low FPS it can be falling beind a litle.

  3. #13
    I disagree that taking away ProcessMessages is solution. If you do that, application will "hang" (won't respond to paint request, button clicks, etc.). Though I agree it shouldn't be called every iteration. Maybe every tenth iteration or so.

  4. #14
    No the application still works OK but the performance gain is much smaler than I imagined it would be.
    Yes I'm actually testing the source code to see where there may be major bottlenecks.

  5. #15
    @User137
    Did I understand corectly that you intend to calculate force efect on every particle from every other particle? If that is ture than your current code is compleetly wrong as you are only calculating the force effects to current particle of all those who are positioned in the list after the current one.
    This would cause compleetly wrong simulation.
    But on the other hand it would mean that proper code would work even slower as your would need to do even nore calculations

  6. #16
    First loop i runs from 0 to count-2, and is divided for different threads. Second loop j runs from i+1 to count-1. Overall effect will be that each unique pair is calculated once, and once only. Index 0 vs 1 is counted, but index 1 vs 0 is not, and so on for all of them. They have same potential force towards eachother, because i assume they all have same mass, and it is applied to both of them at the same time. ... Well, i could try do that 1 fix where physics is calculated separately from main thread, to get 60 fps all the time possibly.

    You may have also noticed that i modified form.onClose event: if threads are running when click it, it will call for threads to stop and then you have to click it again. Otherwise crash would happen on exit, due to accessing game data after threads finish, but data being freed already. It didn't help if i put a waiting loop in the onClose. That was 1 "fix the wheel with bubblegum"... I'll see if i could fix it aswell.

    Update: Please download from the link again, i made proper threading. It looks slightly spiky, but it's doing 60+ fps while physics is calculating on my computer.
    https://docs.google.com/file/d/0B7FI...it?usp=sharing
    Last edited by User137; 14-06-2013 at 04:42 PM.

  7. #17
    Updated the file twice, second time after a little code cleaning.

  8. #18
    Nice demo! Few notes:
    -too many ops per one star, some reduction helps, for example
    Code:
    d := G_FORCE/(d*d*d);
    - division is one of the slowest ops you can do (just this one line change makes it 20% faster)
    -no use of more than 2 calculation threads on dual-core, more threads than cores makes it slower actually
    -Application.Processmessages is an invitation for reentrancy problems, and at least use interlocked decrement on the thread counter (thread joining would be better, sleep really isn't a synchronization primitive)

  9. #19
    Nice notice (fixed it into my version)
    Code:
    d := G_FORCE/(d*d*d);
    It does mean same thing as:
    Code:
    f:=G_FORCE/(d*d); 
    d:=f/d;
    Also there is no Application.ProcessMessages in that version (you can remove "forms" from gameunit uses list). It was replaced by
    Code:
    while Threads>1 do sleep(1);
    in the physics main thread. It still doesn't hang the application because it's a separate thread. Spiking in framerate is simply because of heavy utilization of CPU i think. Trying with this seems to work too, but i feel like it is actually consuming CPU resources more with loop like that
    Code:
    while Threads>1 do ; // <- Don't do this
    So with this i see an increase in physics loop time.

    It should be ok to have 4 threads even on dualcore, remember that each thread gets different workload. Meaning that other CPU could be without work for longer time, if i only had 2 threads. At the same time people with quadcores can test it too. It might even be faster with 8 threads.

    Also works better if i comment out SetFrameSkipping(false); Showing more realistic framerate (~40) numbers too, when it's not pushed to draw as much as possible.
    Last edited by User137; 14-06-2013 at 06:12 PM.

  10. #20
    Empty while loop is worse, for sure: use TThread.WaitFor. You probably want something like this in your TPhysicsMainThread:

    Code:
     
      threads: array [0..MAX_THREADS-1] of TPhysicsThread;
    
    ...
      
         stars_per_thread := count div MAX_THREADS;
            for i := low(threads) to high(threads) do
                threads[i] := TPhysicsThread.Create(FParent, i * stars_per_thread, (i + 1) * stars_per_thread - 1);
            for i := low(threads) to high(threads) do begin
                threads[i].WaitFor;
                threads[i].Free;
            end;
    Last edited by imcold; 14-06-2013 at 06:22 PM.

Page 2 of 4 FirstFirst 1234 LastLast

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •