# C++ Multithreading unter Windows



## Crymes (20. Dezember 2012)

Hallo,
Kann mir einer sagen, ob es noch andere Möglichkeiten gibt unter Windows Multithreading ohne die Win API zu realisieren?

Zu den Anforderungen: Es sollten zu Beginn des Programms eine variable Anzahl an Threads (ca. 2-8) festgelegt werden, die sich dann während der Laufzeit eine for-Schleife teilen.


----------



## Dragonix (20. Dezember 2012)

Also für das, was du vorhast könnte OpenMP was sein.
Ansonsten gibt's doch Bibliotheken wie Sand am Meer: Jedes größere Toolkit (Qt, wxWidgets, ...) hat Threads, dann gibt's die Posix Threads auch für Windows, Boost, ...
Dass das meiste dann aber vermutlich doch über die Windows API realisiert wird ist dir aber klar?


----------



## Crymes (20. Dezember 2012)

Ok, dann wird es wohl auf die winAPI hinauslaufen, kennt jemand ein Tutorial, wo beschrieben wird wie man X-Threads erzeugt?


----------



## Crysis nerd (21. Dezember 2012)

Ich glaub es gibt eine tolle Lösung von boost. Kannste dich ja selber mal schlau machen, aber wenn ich das richtig in Erinnerung habe, war das besser als alles andere.
edit: gerade gegoogelt, guck dir da mal die 1. größere Codebox an, um einen ersten Eindruck zu bekommen: Threading with Boost - Part I: Creating Threads - antonym

Lg
Lukas


----------



## Crymes (21. Dezember 2012)

Ok, Ich hab das jetzt mit WinAPI angefangen, hier mein jetziger Code:

```
[FONT=Consolas][SIZE=2][COLOR=#008000][FONT=Consolas][SIZE=2][COLOR=#008000][FONT=Consolas][SIZE=2][COLOR=#008000]
//Multithreading initialisieren [/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#008000][FONT=Consolas][SIZE=2][COLOR=#008000][FONT=Consolas][SIZE=2][COLOR=#008000]//(define anzahlthreads in definitionen.h) Threads erstellen[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#008000][FONT=Consolas][SIZE=2][COLOR=#008000][FONT=Consolas][SIZE=2][COLOR=#008000]//Nummern zur Identifizierung der einzelnen threads[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]DWORD threadnummer[anzahlthreads];
[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#008000][FONT=Consolas][SIZE=2][COLOR=#008000][FONT=Consolas][SIZE=2][COLOR=#008000]//Betriebssystemobjekt das die Threads verwaltet[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]HANDLE thread[anzahlthreads];
[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#008000][FONT=Consolas][SIZE=2][COLOR=#008000][FONT=Consolas][SIZE=2][COLOR=#008000]//Threads erzeugen[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff]for[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]([/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff]int[/SIZE][/FONT][/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] index=0; index<=anzahlthreads; index++)
{
thread[index] = CreateThread(0, 0, ThreadFunktion, (LPVOID) index, 0, &threadnummer[index]); 
}
[/SIZE][/FONT][/SIZE][/FONT]
```
Der Code steht ganz am Anfang der main() Funktion.

Ich habe jetzt ein paar Fragen:
-Jeder der 8 Threads ruft doch die gleiche Funktion ThreadFunktion() mit seinem Index 1-8 als übergabewert auf, oder?
Ich hatte mir das jetzt so gedacht, dass jede meiner jetzigen Funktionen mit for-Schleifen noch 2 von-bis Argumente bekommen, so dass ich die Schleifen auf die Kerne aufteilen kann.

-Mein größtes Problem ist im Moment, dass ich nicht weiß, was ich mit der ThreadFunktion() Funkltion anfangen soll, da sie ja sofort 8-Mal vorhanden ist, aber eigentlich immer verschiedene Funktionen ausführen soll?
Praktisch gesagt will ich eigentlich jedem Thread, der ja durch die ThreadFunktion() repräsentiert wird zur Laufzeit immer wieder verschiedene Aufgaben geben. Hab ich da grad nen Blackout oder geht das nicht?


----------



## bingo88 (21. Dezember 2012)

Du suchst dir dann vielleicht doch besser ein Framework, das Worker-Threads bzw. Thread-Pools unterstützt. Wenn du das wirklich mit WinAPI machen willst, musst du dir das nämlich alles selbst mühsam zusammenfrickeln. Ich weiß jetzt allerdings nicht, ob boost das kann (glaube schon), da ich mit boost noch nicht so intensiv zu tun hatte. Müsstest du mal nachsehen.


----------



## Crymes (21. Dezember 2012)

Ok, ich habe mir jetzt mal OpenMP angeschaut und festgestellt, dass man damit eigentlich fast ohne Aufwand seine for-Schleifen paralellisieren kann. Ich glaube die WinAPI-Threads sind eher für Simultane Aufgaben gedacht wie z.B. Streaming und gleichzeitiges decodieren etc. und nicht zur Beschleunigung von einzelnen Befehlen.


----------



## bingo88 (21. Dezember 2012)

Klar kann man die dazu nutzen, ist halt nur aufwändiger.


----------



## Crymes (21. Dezember 2012)

Also ich habe es jetzt hinbekommen das Spiel mit einem #pragma omp parallel for vor jeder for-Schleife zu Kompilieren, es wird aber trotzdem nur 1 CPU-Kern genutzt. Muss ich in visual Studio noch irgendwas einstellen ausser den omp-Reiter?

Edit: Muss ich OpenMP vielleicht noch irgendwie mitteilen, wieviele Threads es nutzen soll?


----------



## Dragonix (21. Dezember 2012)

Äh, du hast jetzt aber nicht einfach vor jede Schleife ein #pragma ... geschrieben, oder? Weil damit das funktioniert (so wie du willst) müsstest du schon ziemlich viel Glück haben...
Hast du dir schonmal einige kleine Anleitungen diesbezüglich angeschaut? Zum Beispiel sowas hier http://www.bero-software.de/tutorials_programming/omp.pdf

Paralleles Programmieren ist definitiv nix triviales mehr, das erfordert durchaus Einarbeitung, Übung und vor allem sehr viel Sorgfalt... Wenn du dich damit noch nicht näher beschäftigt hast würde ich dir mal den Foliensatz einer Vorlesung über Paralleles Programmieren oder ein gutes Buch nahelegen..


----------



## bingo88 (21. Dezember 2012)

Bei Spiel und OpenMP in einem Satz klingeln bei mir jetzt auch erst mal die Alarmglocken  Was hast du denn genau vor?


----------



## Ecle (21. Dezember 2012)

Crymes schrieb:


> Zu den Anforderungen: Es sollten zu Beginn des Programms eine variable Anzahl an Threads (ca. 2-8) festgelegt werden, die sich dann während der Laufzeit eine for-Schleife teilen.


Ein For Schleife teilen? Was genau meinst du damit? Ein Thread arbeitet von 1-20 und der 2. dann von 21 - 40 ?
Das würde nicht wirklich Sinn machen, da reicht auch ein Thread.
Es klingt so als würdest du einfach Multithreading benutzen wollen, ohne wirklich zu wissen ob es in deinem Anwendungsfall Sinn macht. Threads machen nur in bestimmten Fällen wirklich Sinn. Eine einfach Ausgabe mittels std::cout kann man z.B. nicht parallelisieren, da es nicht "Thread safe" ist. Generell kann es immer Probleme geben wenn mehrere Threads auf eine Ressource zugreifen. Man kann den Zugriff synchronisieren, aber dann ist meist der ganze Performancegewinn futsch.
Es gibt noch jede Menge andere Probleme die mit Threads auftauchen können, beispielsweise Deadlocks oder Race-Conditions.
Also wie schon gesagt wurde, mit Threads zu arbeiten ist nicht gerade trivial.


----------



## Skysnake (21. Dezember 2012)

Sonst würde es ja auch jeder machen


----------



## Crymes (22. Dezember 2012)

Dieses Pojekt http://extreme.pcgameshardware.de/p...piel-fragen-und-hilfe-bei-programmierung.html soll paralellisiert werden.
Kurz gesagt geht es um n Bälle die alle gegeneinander überprüft werden müssen, was bei 1000 Bällen und meinem 3.2 GHZ Phenom 2 gerade ca. 90 FPS bedeutet. Meine Idee ist es jetzt, das jeder-mit-jedem, was in einer geschachtelten for-Schleife geschieht, zu parallelelisieren, da dort am Meisten Rechenzeit benötigt wird.

Edit: Ich habe bis jetzt 2 Vermutungen, warum das nicht mukltithreadded läuft: Erstens habe ich VS Express, was ich mir mit heruntergeladenen Bibliotheken zusammengebastelt habe, vielleicht geht es aber trotzdem nicht.
Zweitens sind bei meinem Programm am Anfang keine Bälle vorhanden, womit wahrscheinlich auch nur ein Thread läuft. Kann es sein dass die anzahl dr Threads nicht zur Laufzeit angepasst wird?


----------



## Crymes (22. Dezember 2012)

So, ich hab jetzt mal 2 Versionen zusammengestellt, ihr könnt sie euch hier herunterladen.
Ich würde mich freuen, wenn ihr beide mal testen könntet, sagen wir mit 500 oder 1000 Bällen. Ihr müsst "b" gedrückt halten, damit kleine Bälle kommen. Die großen Bällen am Besten mit einem Rechtsklick auf den Ball entfernen, damit das Programm nicht hängt. 
Löschen tut man die Bälle mit "l".

Wenn ihr Lust habt, dann postet doch bitte so das Ergebnis:

Anzahl Bälle (500 oder 1000)
Anzahl Prozessorkerne und Prozessortyp
Geschwindigkeit (GHZ)

zum Vergleich: Mein Phenom 2 x4 955 macht bei 1000 Bällen mit 4 Kernen und 3.2 GHZ ca. 170 FPS,
Mein AMD Brazos C-60 mit 500 Bällen, 2 Kernen und 1.0-1.3 GHZ ca. 60 FPS.


Muss man eigentlich bei Visual Studio noch irgendwas einstellen, damit AVX und SSE genutzt wird?


----------



## bingo88 (22. Dezember 2012)

Das kannst du in den Compileroptionen einstellen, siehe hier.



Crymes schrieb:


> Edit:  Ich habe bis jetzt 2 Vermutungen, warum das nicht mukltithreadded  läuft: Erstens habe ich VS Express, was ich mir mit heruntergeladenen  Bibliotheken zusammengebastelt habe, vielleicht geht es aber trotzdem  nicht.
> Zweitens sind bei meinem Programm am Anfang keine Bälle  vorhanden, womit wahrscheinlich auch nur ein Thread läuft. Kann es sein  dass die anzahl dr Threads nicht zur Laufzeit angepasst wird?


 Nein, das müsste auch mit VS Express gehen.
Und ja, bei OpenMP wird automatisch überhaupt nichts dynamisch angepasst.


----------

