C++ Multithreading - Threads gleichzeitig ablaufen lassen

Dosenfutter123

Cadet 1st Year
Dabei seit
Mai 2016
Beiträge
10
Guten Morgen,

ich befasse mich derzeit mit Threads in C++. Sinn der Sache vom Multithreading, sollte es ja eigentlich sein, dass die Threads gleichzeitig ablaufen. Um das Prinzip zu verstehen, möchte ich erstmal 100 gleichzeitig laufende Zähler-Threads starten, die alle bis 5 zählen.
Mein Problem ist nur, dass ich die Threads nur nacheinander laufen lassen kann, da ich immer mit einer Iterator-Schleife arbeite:
Code:
#include <iostream>
#include <thread>

using namespace std;

void zaehlebis5()
{
  int a = 0;
   for (a; a<=5; a++)
     cout << a << endl;
}

int main(void)
{
   for (int i = 0; i<= 100; i++)
   {
       thread z(zaehlebis5);
       z.join();
   }

   return 0;
}
Dies scheint mir jedoch wenig sinnvoll, da ich diese Aufgabe auch ohne Threads erledigen könnte. Wie kann ich dies umgehen, sodass meine Threads wirklich parallel ablaufen?

Mit freundlichen Grüßen

Dosenfutter 123
 

HominiLupus

Banned
Dabei seit
Okt. 2013
Beiträge
33.550
Du brauchst eine Berechnung die länger dauert. Derzeit ist der Thread welcher bis 5 zählt schon wieder beendet bevor du den nächsten Thread erstellst.
Lass z.B. ein paar große Primzahlen berechnen.
 

Modin666

Lieutenant
Dabei seit
Apr. 2009
Beiträge
873
Wenn man nur auf einem Rechner das Programm laufen lassen will, bietet sich openMP an. Damit kann man direkt einer Schleife sagen, dass sie parallel laufen soll, eventuell angeben, auf welche kritischen Variablen Acht gegeben werden muss, und und.

Aber das kann ich hier auf die schnelle nicht erklären. Such mal bei google, auch unter dem Stichwort #pragma und openmp.h. Dokus gibt es auch online unter openmp.org, wenn ich das richtig erinnere.

LG
 

Dosenfutter123

Cadet 1st Year
Ersteller dieses Themas
Dabei seit
Mai 2016
Beiträge
10
Danke für die schnellen Antworten

Du brauchst eine Berechnung die länger dauert. Derzeit ist der Thread welcher bis 5 zählt schon wieder beendet bevor du den nächsten Thread erstellst.
D.h. bei komplexeren Berechnungen können andere Threads starten, während andere noch garnicht abgeschlossen sind?

Wenn man nur auf einem Rechner das Programm laufen lassen will, bietet sich openMP an. Damit kann man direkt einer Schleife sagen, dass sie parallel laufen soll, eventuell angeben, auf welche kritischen Variablen Acht gegeben werden muss, und und.
Gibt es dann garkeine einfache Möglichkeit meinem Programm zu sagen, dass er mehrere Tasks wirklich gleichzeitig starten soll und parallel ausführen soll?
Was ist dann der große Vorteil von Threads wenn ich alles genauso mit Funktionen erledigen könnte?

Gruß Dosenfutter123
 

0-8-15 User

Commodore
Dabei seit
Jan. 2008
Beiträge
4.414
Zuletzt bearbeitet: (Links eingefügt)

HominiLupus

Banned
Dabei seit
Okt. 2013
Beiträge
33.550
D.h. bei komplexeren Berechnungen können andere Threads starten, während andere noch garnicht abgeschlossen sind?
Genau das ist Sinn und Zweck von Threads: 2 oder mehr Threads nebeneinander laufen zu lassen.
Gleichzeitig starten kann nicht gehen, denn dein Thread der die Threads startet kann selbst ja nur sequentiell arbeiten und Thread 2, dann Thread 3, dann Thread 4, etc. nacheinander starten. Du könntest eine Art Kaskade bauen d.h. 2 Threads starten, diese 2 Threads selber starten wieder 2 Threads etc. aber das ist Blödsinn weil schwerer sinnvoll zu programmieren und kein praktischer Nutzen.

Funktionen in einem Thread arbeiten alles nacheinander ab mit nur einem Kern. Threads hingegen können parallel arbeiten und alle Kerne deiner CPU auslasten. D.h. mit Threads 4 mal schneller sein auf einem Quadcore.

Also: gleichzeitig starten kannst du praktisch nicht bzw. ist nicht sinnvoll. Parallel ausführen hingegen geht sehr wohl.
 

Modin666

Lieutenant
Dabei seit
Apr. 2009
Beiträge
873
Ich kenne mich mit c++ nicht im Detail aus, genauer kenne ich die thread-Klasse nicht, habe das gerade nur kurz nachgelesen. Mein Vorredner hat wohl Recht.

Deine for-Schleife erzeugt viele klassen vom typ thread. Die werden alle ausgeführt, sodass du, wenn das schnell genug geht, mehrere Threads gleichzeitig hast. Schau mal auf cplusplus.com noch, da findest du, wenn du nach thread suchst, auch ein Beispiel, dass deinen Denkprozess unterstützt.

Durch den join-befehl untergräbst du aber auch deine Bemühung, wenn ich das richtig gelesen habe. Denn dadurch wird das Programm pausiert, bis der thread fertig ist. Würde ich erst mal weg lassen und zum Testen mal ein cout in deine funktion reinschreiben, damit du verfolgen kannst, wie die threads gerade ticken.

Aber wie gesagt, wenn du Schleifen parallelisiert laufen lassen willst, schau dir mal openMP an. Wenn ich das recht verstehe, setzt du mit thread nur gezielt eine Aufgabe auf einen Thread, was ein erster Schritt zu mehr Parallelität ist, aber eben nicht das tut, was du willst, so wie es klingt, nämlich alle Prozessorkerne auszulasten. openMP ist da sehr hilfreich, und wenn du über mehrere Rechner das ganze verteilen willst, MPI, oder sogar ein Mix daraus. Moderne Simulationscodes nutzen dass beispielsweise. Für dich wäre aber openMP sicher sinnvoll.

LG
Ergänzung ()

@ 0815: Ja, habe ich. Aber wie ich gerade geschrieben habe, muss ich mich bei c++ manchmal noch einlesen. Ich schreibe meist C.

PS: @ Homni_Lupus: Man kann Threads schon parallel mit openMP abfeuern. Ja, genaugenommen starten die auch nacheinander, aber openMP verteilt, wenn man es richtig machst, Aufgaben wie eine for-schleife auf so viele Threads, wie da sind oder man spezifiziert. Geht also doch.

Hier was zum recherchieren:
http://openmp.org/wp/
https://de.wikipedia.org/wiki/OpenMP
https://www.youtube.com/watch?v=a-1bX5EWS2Y
https://www.youtube.com/watch?v=fn2VAUSw6cI

Der dritte Link zeigt Beispiele für die Nutzung, insbesondere für for-schleifen.
 
Zuletzt bearbeitet:

Dosenfutter123

Cadet 1st Year
Ersteller dieses Themas
Dabei seit
Mai 2016
Beiträge
10
Ok jetzt kommt endlich Licht ins Dunkle :)

Das heißt den join-Befehl benutze ich nur, wenn ich wirklich will, dass mein Thread bis zu diesem Zeitpunkt fertig-gerechnet hat. Wenn ich also einen Thread starte und in der nächsten Zeile gleich joine, könnte ich genausogut mit Funktionen arbeiten. Wenn ich den Thread aber starte, derzeit in der main() z.B. was anders ausführe & dann erst joine, ist der Thread von nutzen, da sowohl der Thread als auch die main() weiter ausgeführt werden (Korrigiert mich bitte, sollte etwas nicht stimmen).

Dass ich Prozesse wirklich parallel starte, war von vornherein keine Absicht & das werde ich bei meinen Low-Level-Programmieraufgaben wohl erstmal nicht brauchen. Wichtig war mir vor allem, das Prinzip der Threads zu verstehen. Trotzdem danke für den Hinweis Modin666
 

HominiLupus

Banned
Dabei seit
Okt. 2013
Beiträge
33.550
0-8-15 hat Recht, und ja deine Erklärung stimmt auch.
 

Modin666

Lieutenant
Dabei seit
Apr. 2009
Beiträge
873
Dann habe ich das wohl missverstanden. Sry. Klar es macht einen Unterschied, ob ich einzelne Threads selbst gesteuert starte, weil ich es so machen muss, damit das Programm richtig läuft, oder ob man weiß, das etwas einfach nur verteilt werden soll, und man das nicht gesteuert braucht bzw. die Steuerung unkritisch ist. Aber selbst da bietet openMP die Möglichkeit, steuernd einzugreifen, wenn eine gewisse Variable beispielsweise erst mal fertig gerechnet werden muss, bevor ein anderen Thread zugreifen kann. Ich denke, beides hat Vorteile bzw. seinen Nutzen. Kann der TE ja für sich entscheiden, ob und was sinnvoll ist für seine Aufgabe. Ich wollte nur behilflich sein und einen Anregung geben. Ich hab selbst nur 2 mal testweise etwas parallel programmiert und nutzte im Moment eine fertige Bibliothek für Simulationen.

LG
 
V

VikingGe

Gast
Die C++-Standardbibliothek bietet ja mehr als nur die thread-Klasse - für Synchronisation neben Standard-Locking-Kram eben auch sowas wie future.
OpenMP mag nett sein, ist aber eben kein Standard-C++ und funktioniert nicht mit jedem Compiler.
 

Modin666

Lieutenant
Dabei seit
Apr. 2009
Beiträge
873
Danke, wieder was gelernt. Und ja, dass openmp kein c++-Standard ist, weiß ich wohl. Müsste man uU selbst noch auf dem Rechner bekannt machen.
 
Top