Seite 1 von 2

Tutorial: Parallele Programmierung in PB

Verfasst: 28.03.2009 16:10
von cxAlex
Parallele Programmierung wird dieser Tage immer wichtiger. DualCore ist schon Standart, QuadCore auch schon fast normal und bis 2010 will Intel 6 Kern Desktop CPUs herausbringen.

Um die Power mehrerer Prozessorkerne zu nutzen muss man aber zwangsläufig auf Threads setzen, ansonst hat man genau gar nichts davon.

Nun sehe ich hier im Forum immer wieder Leute die vor Threads zurückschrecken (eben weil Sie sie nicht verstehen), total falsche Verwendung und auch sonst die abenteuerlichsten Verwendungen von Threads.

Also muss ein Tutorial her. :mrgreen:

Parallele Programmierung in PB: Threads & mehr

Geplant:
  • Threads in PB
  • Thread - Kommunikation
  • Verwaltung mehrer Threads
  • Synchronisation von Threads
  • Gefahren bei der Verwendung von Threads (Death Lock, Race Conditions, ...)
Wenn anderweitige Fragen auftauchen werde ich versuchen auch diese zu beantworten.

Ich würde mit dem Tutorial morgen oder am Montag beginnen, besteht Interesse?

Gruß, Alex

Re: Tutorial: Parallele Programmierung in PB

Verfasst: 28.03.2009 17:32
von ts-soft
cxAlex hat geschrieben:DualCore ist schon Sandart
Bei Netbook oder Notebook am Strand dürfte das hinhauen :mrgreen:
cxAlex hat geschrieben: Ich würde mit dem Tutorial morgen oder am Montag beginnen, besteht Interesse?
Sicherlich doch :allright:

Re: Tutorial: Parallele Programmierung in PB

Verfasst: 28.03.2009 17:33
von X360 Andy
cxAlex hat geschrieben:
Ich würde mit dem Tutorial morgen oder am Montag beginnen, besteht Interesse?
Immer doch :allright:
Aber gab es sowas bzw gibt es sowas nicht schon ? (Hab leider grad keine Zeit zum suchen)

Verfasst: 28.03.2009 18:52
von KeyKon
Auf jeden Fall :allright:

Verfasst: 28.03.2009 20:13
von Andesdaf
cxAlex hat geschrieben:Ich würde mit dem Tutorial morgen oder am Montag beginnen, besteht Interesse?
keine Frage :)

Verfasst: 28.03.2009 23:49
von cxAlex
Toll das so viel Interesse besteht. Ich denke es wird eher Montag als morgen werden, aber vlt. krieg ichs hin schon morgen die ersten Schritte zu posten.

@X360 Andy:

Es gibt eine Erklärung was Threads sind und was man damit machen darf und was nicht (Windows/PB/DX/... - Einschränkungen) von PMV, dort werden aber keine Beispiele oder Anwendungsmöglichkeiten erklärt oder vorgezeigt.

Übrigens empfehle ich PMVs Thread vor dem Tutorial zu lesen:

http://www.purebasic.fr/german/viewtopic.php?t=18374

Gruß, Alex

Verfasst: 29.03.2009 11:21
von cxAlex
Grundlagen: Threads in PB

PB stellt einem schon von Haus aus Funktionen zur Erstellung und Verwaltung von Threads bereit. Warum man Pause/Resume/Kill-Thread eher vermeiden sollte werde ich später im Tutorial noch erläutern.

Wie starte ich einen Thread in PB?

Dafür gibt es in PB den Befehl CreateThread(). Dieser erwartet den Pointer auf eine Procedure, und einen Übergabeparameter. Wobei wir schon bei der 1. Fehlerquelle währen:

Wichtig: Auch wenn euer Thread diesen Parameter nicht braucht müsst ihr ihn in die Procedurenparameter schreiben, sonst kommt es früher oder später zu einem Stack Fehler.

Nun starten wir unseren 1. Thread mit PB:

Code: Alles auswählen

; Thread Procedure. Parameter nicht vergessen!
Procedure MyThread(dummy)
  MessageRequester("Thread", "Ich bin ein Thread")
EndProcedure

; Thread erstellen. Pointer auf Procedure mit @ ermitteln
Thread = CreateThread(@MyThread(), 0)
MessageRequester("Main", "Ich bin das Hauptprogramm")
Das war ja noch gar nicht so schwer. Nun wollen wir dem Thread aber natürlich auch Parameter übergeben, in diesem Beispiel den Text der angezeigt werden soll:

Wichtig: Sobald in Threads Strings vorkommen sollte man immer die Compiler-Option Thread-Safe verwenden.

Code: Alles auswählen

; Thread Procedure.
Procedure MyThread(*Text.s)
  MessageRequester("Thread", *Text)
EndProcedure

; Thread erstellen. Pointer auf Procedure mit @ ermitteln
; Nun übergeben wir einen Parameter
Text.s = "Ich bin ein Thread"
Thread = CreateThread(@MyThread(), @Text)
MessageRequester("Main", "Ich bin das Hauptprogramm")
Auch bis hierher noch ganz einfach. Nun wollen wir aber meist nicht nur einen Parameter übergeben sondern mehrere. Da man an den Thread nur 1. übergeben kann lösen wir das ganze mit einer Struktur, in die wir alle Werte schreiben die wir brauchen, und an den Thread übergeben. Dafür schreiben wir uns eine kleine Launcher Procedure:

Code: Alles auswählen

; Thread Parameter
Structure Thread_Parameter
  *Title ; Titel
  *Text ; Text
  Flags.i ;Parameter
EndStructure

; Thread Procedure
Procedure MyThread(*Thread.Thread_Parameter)
  Protected Title.s, Text.s
  Title.s = PeekS(*Thread\Title)
  Text.s = PeekS(*Thread\Text)
  MessageRequester(Title, Text, *Thread\Flags)
 
  ; Speicher aufräumen
  FreeMemory(*Thread\Title)
  FreeMemory(*Thread\Text)
  FreeMemory(*Thread)
EndProcedure

; Thread - Starter
Procedure Thread_Launcher(Title.s, Text.s, Flags = 0)
  ; Neue Thread - Parameter anlegen
  Protected *Thread.Thread_Parameter = AllocateMemory(SizeOf(Thread_Parameter))
 
  ; Thread - Paramter schreiben
 
  ; Ich verwende absichtlich keine nativen Strings in der Struktur da man diese
  ; manuell freigeben müsste, daher Speicherblöcke
  *Thread\Title = AllocateMemory(StringByteLength(Title) + SizeOf(Character))
  PokeS(*Thread\Title, Title)
  *Thread\Text = AllocateMemory(StringByteLength(Text) + SizeOf(Character))
  PokeS(*Thread\Text, Text)
  *Thread\Flags = Flags

  Thread = CreateThread(@MyThread(), *Thread)
 
  ProcedureReturn Thread
EndProcedure

; Thread starten
Thread_Launcher("Thread","Ich bin ein Thread")
Thread_Launcher("Thread","Ich bin auch ein Thread")
MessageRequester("Main", "Ich bin das Hauptprogramm")
Wichtig: Der Thread muss seine Parameter am Ende immer freigeben, sonst ensteht ein Memory - Leak

So, nun haben wir bereit ein Anwendungsbeispiel: eine MessageBox die die Programmausführung nicht blockiert.
Das war ein kleines Beispiel wie man Threads in PB erstellen kann. Eigentlich sollte bis hierher alles klar sein, wenn es Fragen gibt nur her damit!

Verfasst: 29.03.2009 13:43
von hjbremer
muß es nicht heißen *Thread\Flags = Flags anstatt Flags = Flags ?

du schreibst
; Ich verwende absichtlich keine nativen Strings in der Struktur da man diese
; manuell freigeben müsste, daher Speicherblöcke
was heißt das genau ?? du gibst doch mit FreeMemory(*Thread\Title) alles einzeln frei.

Ansonsten weitermachen, da ich bisher mit THREADS noch garnichts gemacht habe und es eigentlich auch nicht nötig war, wer weiß das schon, werde ich deine Posts aufmerksam verfolgen :allright:

Verfasst: 29.03.2009 13:49
von cxAlex
hjbremer hat geschrieben:muß es nicht heißen *Thread\Flags = Flags anstatt Flags = Flags ?
Ups, kleiner Tippfehler, danke.
; Ich verwende absichtlich keine nativen Strings in der Struktur da man diese
; manuell freigeben müsste, daher Speicherblöcke
> was heißt das genau ?? du gibst doch mit FreeMemory(*Thread\Title) alles einzeln frei.

Ich verwende kein Title.s, Text.s, sondern eben *Title, *Text und speicher alles in Speicherblöcke, also ich verwende keine nativen PB Strings da sonst der PB Stringmanager mitmischen würde und ich eine extra Funktion zum freigeben der Strings in der Struktur brauchen würde.
(Es gibt schon einen Weg dafür aber der kann sich mit der nächsten PB - Version schon wieder ändern und so sollte es immer gehen)

Verfasst: 29.03.2009 14:04
von hjbremer
ein kleines Problem nun
wenn ich in Compileroptionen threadsicheres Executable erstellen einschalte gibt es einen readerror at adress 8 mit PB 4.3

und gerade mit 4.2 getestet, da gehts