Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Threads SFML2.3  (Read 3978 times)

0 Members and 1 Guest are viewing this topic.

Rarebit

  • Newbie
  • *
  • Posts: 2
    • View Profile
    • Email
Threads SFML2.3
« on: July 11, 2015, 02:55:44 am »
Hello

i have a question about the Threads.
Hardeware: HP Zbook with i7 4700MQ
Software: Win8, Visual Studio 13 Professional SFML 2,3

My Programm process the numeric integral of Biot Savart with the euler technic.
https://en.wikipedia.org/wiki/Biot%E2%80%93Savart_law

It has a vector with dim 3, every of this hould a dim 3 double vector as element.
Now the programm process every point (with natural numbers), x0-20(y0-20(z0-20)).
At every point it calculalte the magnet field vector and save it in the element of the "cube".

So i splitted the cube up in layers and gave every thread the same nummber of layers, the one, which where still not allocated to a thread, i pushed one at each thread, so long i had some layer in list.
In this example 20%4 => 4Threads*4+1Layers

Time to render:
Threads: Time in Minutes:
1.   ca. 2:35
2.   1:49
3.   1:43
4.   1:37
8.   1:57

Whats going wrong?
The frustating thing is, with 4threads cpu at 70%, with 8. 100% but 4 are faster.  :o

Maybe some information for me?
If someone want to see some other code, tell me :)

Regards,
Rarebit.

The code with thread handling.
        int PartIntervall = game.DataBase.MagnetVectorList.size() / MaxThreads;
        int PartIntervallRest = game.DataBase.MagnetVectorList.size() % MaxThreads;
       
        vector<int> StartMod;
        StartMod.resize(MaxThreads, 0);
        vector<int> EndMod;
        EndMod.resize(MaxThreads, 0);
       
        for (int i = StartMod.size()-1; i > -1 && PartIntervallRest > 0 ; i--)
        {
                EndMod[i] = PartIntervallRest;
                StartMod[i] = PartIntervallRest - 1;
                PartIntervallRest--;
        }
       
       
       
        sf::Thread Thread1(bind(&forCoilMagneticFieldAtPointAsVector, &game, 0 + StartMod[0], PartIntervall + EndMod[0]));
        sf::Thread Thread2(bind(&forCoilMagneticFieldAtPointAsVector, &game, PartIntervall + StartMod[1], PartIntervall * 2 + EndMod[1]));
        sf::Thread Thread3(bind(&forCoilMagneticFieldAtPointAsVector, &game, PartIntervall * 2 + StartMod[2], PartIntervall * 3 + EndMod[2]));
        sf::Thread Thread4(bind(&forCoilMagneticFieldAtPointAsVector, &game, PartIntervall * 3 + StartMod[3], PartIntervall * 4 + EndMod[3]));
        //sf::Thread Thread5(bind(&forCoilMagneticFieldAtPointAsVector, &game, PartIntervall * 4 + StartMod[4], PartIntervall * 5 + EndMod[4]));
        //sf::Thread Thread6(bind(&forCoilMagneticFieldAtPointAsVector, &game, PartIntervall * 5 + StartMod[5], PartIntervall * 6 + EndMod[5]));
        //sf::Thread Thread7(bind(&forCoilMagneticFieldAtPointAsVector, &game, PartIntervall * 6 + StartMod[6], PartIntervall * 7 + EndMod[6]));
        //sf::Thread Thread8(bind(&forCoilMagneticFieldAtPointAsVector, &game, PartIntervall * 7 + StartMod[7], PartIntervall * 8 + EndMod[7]));
       
        Thread1.launch();
        Thread2.launch();
        Thread3.launch();
        Thread4.launch();
        //Thread5.launch();
        //Thread6.launch();
        //Thread7.launch();
        //Thread8.launch();
       
        sf::Thread Thread0(bind(&getProcess, &game)); //Überwachungsthread mit Fortschrittsanzeige
        Thread0.launch();
       
        Thread1.wait();
        Thread2.wait();
        Thread3.wait();
        Thread4.wait();
        //Thread5.wait();
        //Thread6.wait();
        //Thread7.wait();
        //Thread8.wait();
       
        Thread0.terminate();

 

The calculation function
void forCoilMagneticFieldAtPointAsVector(game* game, int StartIntervall, int EndIntervall)
{

        for (size_t i = StartIntervall; i < EndIntervall; i++) //Jede grade Koordinate die Leiter abbarbeiten, hier zu beachten ist die Aufteilung den Würdfels in Scheiben
        {
                for (size_t y = 0; y < game->DataBase.MagnetVectorList[i].size(); y++)
                {
                        for (size_t j = 0; j < game->DataBase.MagnetVectorList[i][y].size(); j++)
                        {
                                //Spulen abarbeiten
                                for (size_t CoilListCounter = 0; CoilListCounter < game->DataBase.CoilList.size(); CoilListCounter++)
                                {
                                        coil CoilHolder = game->DataBase.CoilList[CoilListCounter]; //Kopier erstellen um Höhere Bandbreite zu Schaffen und jedem Thread schnellere Zugriffe zu ermöglichen

                                        int MaxParts = CoilHolder.getMaxParts(game->DataBase.PartModivication); //Anzahl der Einzelteile der Spule

                                        for (size_t Part = 0; Part < MaxParts; Part++)//eine Spule nach einer Genauigkeit abarbeiten
                                        {


                                                vector<double> vdPositionToNextPosition = vector_math_sub
                                                        (
                                                        CoilHolder.getPosition          //erster Vektor mit Parametern
                                                        (
                                                        (CoilHolder.getLegth() / MaxParts)*Part
                                                        ),

                                                        CoilHolder.getPosition          //zweiter Vektor mit Parametern
                                                        (
                                                        (CoilHolder.getLegth() / MaxParts)*(Part + 1)
                                                        )
                                                        );

                                                vector<double> vdDetectionPoint; //der Punkt an welchem gemessen wird als Input für Biot Savart, ist hier gegeben durch die Itteration der Graden Koordinatenpunkte
                                                vdDetectionPoint.push_back(i);
                                                vdDetectionPoint.push_back(y);
                                                vdDetectionPoint.push_back(j);

                                                game->DataBase.MagnetVectorList[i][y][j] = vector_math_add
                                                        (
                                                        game->DataBase.MagnetVectorList[i][y][j],        //erster Vektor mit Parametern

                                                        biot_savart                                                                      //zweiter Vektor mit Paramtern
                                                        (
                                                        vector_math_skalarmult(game->DataBase.LengthSImult, CoilHolder.getPosition((CoilHolder.getLegth() / MaxParts)*Part)),
                                                        vector_math_skalarmult(game->DataBase.LengthSImult, vdPositionToNextPosition),
                                                        vector_math_skalarmult(game->DataBase.LengthSImult, vdDetectionPoint),
                                                        1,
                                                        CoilHolder.getAmperage()
                                                        )
                                                        );                             
                                        }
                                }
                        }
                }
        }
}

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 10838
    • View Profile
    • development blog
    • Email
Re: Threads SFML2.3
« Reply #1 on: July 11, 2015, 09:03:16 am »
Welcome to the field of parallel programming, where using more threads won't necessarily make your things faster. Every thread has an overhead and the system resource utilization can vary. For example your CPU has 4 cores and allows 8 threads. Now if you try to use all 8 threads for you application, the OS and all your other applications essentially have to fight for some CPU time as well, which will cause the OS to suspend some of your applications threads for a while to do other work.

If you want to do more parallel programming, I suggest you get yourself a book on said topic, since it's not a trivial one. ;)

You could also try it with 6 or 7 threads, that way you don't try to hog your system too much.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Re: Threads SFML2.3
« Reply #2 on: July 11, 2015, 09:45:06 am »
I agree with what eXpl0it3r said.

Furthermore, is your thread function even thread-safe? It leads to concurrent calls to the game object, are those protected? And don't use sf::Thread::terminate() unless you know exactly what you're doing.

If your compiler supports C++11, use standard threads instead of SFML ones.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Jesper Juhl

  • Hero Member
  • *****
  • Posts: 1405
    • View Profile
    • Email
Re: Threads SFML2.3
« Reply #3 on: July 11, 2015, 12:03:48 pm »
Just to expand a bit on the existing (very good) answers.

The more threads you have the more scheduling overhead you also have.

The more threads you have the more locking overhead you have (unless you use lock-free algorithms - a rather advanced topic).

The more threads you have the more you need to be careful to access data in a cache friendly manner or you risk writes from one thread invalidating cache lines used by other threads, which can really kill performance.

The more threads you have the more difficult it becomes to reason about the state of your program, like; what locks are needed/aquired at any given time, what order must locks be taken in where, what threads are currently executing (and where), etc etc.

The more threads you have the harder it becomes to debug the application since the debugger will alter the timings between the threads.

The fact that adding more threads decrease performance is not really something to be surprised about. Getting more performance by using threads requires a fair amount of work and knowledge and is by no means a trivial or easy thing. Especially since it gets a lot harder to make the program correct. You need to ensure that all functions called by the threads are thread-safe. You need to ensure that all data access is properly synchronized. You need to be really careful with exceptions escaping your threads. Etc.

I usually recommend that people stick to a single thread unless they know C++ really well, have thoroughly researched all the issues that threading bring to the table and are absolutely certain that the issue they are facing can actually benefit from threads.
In short; writing correct threaded programs is really hard and getting them to perform well is even harder. It is (IMHO) "expert only" territory and should be approached with caution.
« Last Edit: July 11, 2015, 03:51:22 pm by Jesper Juhl »

Rarebit

  • Newbie
  • *
  • Posts: 2
    • View Profile
    • Email
Re: Threads SFML2.3
« Reply #4 on: July 11, 2015, 06:44:24 pm »
First i want to thank you for your informations.

"Thread save", what do you want to say with that, i looked it up at wiki.
But it is save in my programm. The only thing i can imagine, which can slow it is:
The threads write there results everytime in a database, call the current status of the vector and add something and save it again in the databasevector.
Now i thougth that it is would be fixed, because each thread has its own layer. So it only save only on its own layer, but well i am a noob :D how could it slow down, every thread has its own informations.
They do not interrupt each other i think.

I will get inforamtions about all the topics you all named an will be see what i learn to fix it!

@Nexus the trhead i terminate is only a output loop to show how much vectors to render :)
And thanks for the information about c++11 threads

Regards,
Rarebit.

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Re: Threads SFML2.3
« Reply #5 on: July 11, 2015, 06:52:20 pm »
"Thread save", what do you want to say with that
That's probably the most fundamental thing you should know when working with threads :P

@Nexus the trhead i terminate is only a output loop to show how much vectors to render :)
It doesn't matter at all what the thread does. Just read the documentation of terminate() and why you should not use it.

I don't think it is necessary to comment on the rest of your post -- Jesper Juhl has already said everything that's important. You lack basic knowledge about threading, you have to do some research before even thinking about writing multi-threaded code.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Jesper Juhl

  • Hero Member
  • *****
  • Posts: 1405
    • View Profile
    • Email
Re: Threads SFML2.3
« Reply #6 on: July 11, 2015, 07:05:43 pm »
"Thread save", what do you want to say with that

1. It's "Thread safe", not "save".
2. Try google - it would have lead you to https://en.m.wikipedia.org/wiki/Thread_safety
« Last Edit: July 11, 2015, 07:09:52 pm by Jesper Juhl »

 

anything