Multicore Programmierung

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
captain_hesse
Beiträge: 138
Registriert: 17.05.2009 18:55
Computerausstattung: Windows 7 Ultimate 64 Bit / AMD Phenom II 1090T, 6x3200 MHz / AMD HD-6850 / PureBasic 5.1 (x86) (x64)
Wohnort: Saarland

Multicore Programmierung

Beitrag von captain_hesse »

Hallo
Es geht mir darum verschiedene Schleifen, die millionenfach aufgerufen werden in einzelne Threads auszulagern und dann parallel ablaufen zu lassen. Dazu habe ich folgendes Testprogramm geschrieben

Code: Alles auswählen

OpenConsole()

Global Dim buffer(5) 
Global mutex=CreateMutex()



Procedure liste(a,x)  
  LockMutex(mutex)
  buffer(a)=x
  UnlockMutex(mutex)
EndProcedure


Procedure s1(dummy)
  For x=1 To 10
    a=1
    liste(a,x)
  Next
EndProcedure 

Procedure s2(dummy)
  For x=1 To 10
    a=2
    liste(a,x)
  Next
EndProcedure 

Procedure s3(dummy)
  For x=1 To 10
    a=3
    liste(a,x)
  Next
EndProcedure 

Procedure s4(dummy)
  For x=1 To 10
    a=4
    liste(a,x)
  Next
EndProcedure 

Procedure s5(dummy)
  For x=1 To 10
    a=5
    liste(a,x)
  Next
EndProcedure 


multicore=#False  ;für Multi-Threading auf #True ändern


time_start=ElapsedMilliseconds()

For l=1 To 1000000
If multicore=#False  
  s1(dummy)
  s2(dummy)
  s3(dummy)
  s4(dummy)
  s5(dummy)
Else
t1=CreateThread(@s1(),0)
t2=CreateThread(@s2(),0)
t3=CreateThread(@s3(),0)
t4=CreateThread(@s4(),0)
t5=CreateThread(@s5(),0)
WaitThread(t1)
WaitThread(t2)
WaitThread(t3)
WaitThread(t4)
WaitThread(t5)
EndIf
Next

time_stop=ElapsedMilliseconds()

PrintN(Str(time_stop-time_start))
Input()
es arbeitet je nach einstellung die Schleifen serial oder parallel ab nur das die parallele variante viel langsamer ist. Ich denke das CreateThread() viel zu langsam initialisiert wird. Deshalb habe ich dann noch eine zweite Variante

Code: Alles auswählen

OpenConsole()

Global Dim buffer(5) 
Global mutex=CreateMutex()
Global sp1_start=CreateSemaphore()
Global sp1_stop=CreateSemaphore()
Global sp2_start=CreateSemaphore()
Global sp2_stop=CreateSemaphore()
Global sp3_start=CreateSemaphore()
Global sp3_stop=CreateSemaphore()
Global sp4_start=CreateSemaphore()
Global sp4_stop=CreateSemaphore()
Global sp5_start=CreateSemaphore()
Global sp5_stop=CreateSemaphore()



Procedure liste(a,x)  
  LockMutex(mutex)
  buffer(a)=x
  UnlockMutex(mutex)
EndProcedure


Procedure s1(dummy)
  Repeat
  WaitSemaphore(sp1_start)
  For x=1 To 10
    a=1
    liste(a,x)
  Next
  SignalSemaphore(sp1_stop)
  ForEver
EndProcedure 

Procedure s2(dummy)
  Repeat
  WaitSemaphore(sp2_start)
  For x=1 To 10
    a=2
    liste(a,x)
  Next
  SignalSemaphore(sp2_stop)
  ForEver
EndProcedure 

Procedure s3(dummy)
  Repeat
  WaitSemaphore(sp3_start)
  For x=1 To 10
    a=3
    liste(a,x)
  Next
  SignalSemaphore(sp3_stop)
  ForEver
EndProcedure 

Procedure s4(dummy)
  Repeat
  WaitSemaphore(sp4_start)
  For x=1 To 10
    a=4
    liste(a,x)
  Next
  SignalSemaphore(sp4_stop)
  ForEver
EndProcedure 

Procedure s5(dummy)
  Repeat
  WaitSemaphore(sp5_start)
  For x=1 To 10
    a=5
    liste(a,x)
  Next
  SignalSemaphore(sp5_stop)
  ForEver
EndProcedure 


t1=CreateThread(@s1(),0)
t2=CreateThread(@s2(),0)
t3=CreateThread(@s3(),0)
t4=CreateThread(@s4(),0)
t5=CreateThread(@s5(),0)


time_start=ElapsedMilliseconds()

For l=1 To 1000000
  SignalSemaphore(sp1_start)
  SignalSemaphore(sp2_start)
  SignalSemaphore(sp3_start)
  SignalSemaphore(sp4_start)
  SignalSemaphore(sp5_start)
  WaitSemaphore(sp1_stop)
  WaitSemaphore(sp2_stop)
  WaitSemaphore(sp3_stop)
  WaitSemaphore(sp4_stop)
  WaitSemaphore(sp5_stop)
Next

time_stop=ElapsedMilliseconds()

PrintN(Str(time_stop-time_start))
Input()
das ist zwar schon schneller aber immer noch langsamer als die schleifen einfach nacheinander abzuarbeiten. Vielleicht hat jemand eine Idee wie man das Programm schreiben müßte damit es schneller läuft.

Ich denke das dies ein sehr interessantes Thema für dieses Forum ist da die Multicore Programmierung zukünfitg wohl immer mehr zu einsatz kommen wird. Vielleicht weiß ja auch schon jemand mehr darüber, ob es für PB sowas wie OpenMP gibt oder geplant ist.

Hier noch ein Link der sehr treffend beschreibt was ich meine.
http://de.wikipedia.org/wiki/OpenMP


Viele Grüße
Armin
Windows 7 Ultimate 64 Bit / AMD Phenom II 1090T, 6x3200 MHz / AMD HD-6850 / PureBasic 5.1 (x86) (x64)
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: Multicore Programmierung

Beitrag von ts-soft »

Wer sagt, das durch Threads irgend etwas schneller wird? Wenn längere Berechnungen o. ä.
durchgeführt werden, braucht man den Benutzer nicht warten lassen. Aber schneller wird es
im allgemeinen nicht. Durch die ganze Absicherung wird ein Programm mit Threads auch oft
langsamer, z.B. wenn man solche Popel-Aufgaben reinpackt wie Du.
In einer normalen Anwendung, wo noch andere Nebenher laufen und das OS dafür sorgt, das
diese ordenlich verteilt werden, sind Threads meist nicht von Vorteil. In Spielen, wo das
OS nichts zum verteilen hat, weil ja nicht viel anderes als das Spiel läuft, sind Threads schon
eher sinnvoll.
Wenn also Threads nutzen, dann bitte für Aufgaben die sehr Zeitintensiv sind und nicht wie
Dein obiges Beispiel, wo das Erzeugen und absichern des Threads länger dauert als der Thread
selber :mrgreen:
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
captain_hesse
Beiträge: 138
Registriert: 17.05.2009 18:55
Computerausstattung: Windows 7 Ultimate 64 Bit / AMD Phenom II 1090T, 6x3200 MHz / AMD HD-6850 / PureBasic 5.1 (x86) (x64)
Wohnort: Saarland

Re: Multicore Programmierung

Beitrag von captain_hesse »

ts-soft hat geschrieben:Wer sagt, das durch Threads irgend etwas schneller wird? Wenn längere Berechnungen o. ä.
durchgeführt werden, braucht man den Benutzer nicht warten lassen. Aber schneller wird es
im allgemeinen nicht. Durch die ganze Absicherung wird ein Programm mit Threads auch oft
langsamer, z.B. wenn man solche Popel-Aufgaben reinpackt wie Du.
In einer normalen Anwendung, wo noch andere Nebenher laufen und das OS dafür sorgt, das
diese ordenlich verteilt werden, sind Threads meist nicht von Vorteil
Na dann erkläre mir doch bitte mal wie man ein Programm für einen Mehrkernprozessor optimieren soll ohne dafür Threads zu benutzen.
Und warum sind Programme die für Mehrkern CPUs optimiert sind dann meistens schneller mit der Arbeit fertig als Programme die nur einen Kern benutzen :?
In Spielen, wo das OS nichts zum verteilen hat, weil ja nicht viel anderes als das Spiel läuft, sind Threads schon eher sinnvoll.
Genau das ist ja auch Sinn und Zweck der Übung. Ich wollte gerne das der Zuggenerator in meinem Schachprogramm die Züge der einzelnen Figurentypen parallel berechnet, also auf die einzelnen Kerne der CPU verteilt um dadurch Rechenzeit zu gewinnen. Und das sind dann keine Popel-Aufgaben mehr wie sie oben nur als Beispiel dienen.
Windows 7 Ultimate 64 Bit / AMD Phenom II 1090T, 6x3200 MHz / AMD HD-6850 / PureBasic 5.1 (x86) (x64)
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: Multicore Programmierung

Beitrag von ts-soft »

captain_hesse hat geschrieben:Und das sind dann keine Popel-Aufgaben mehr wie sie oben nur als Beispiel dienen.
Warum sollen wir also die Zeit der sinnlosen Beispiele Messen?
Für Deine Beispiele sind Threads blödsinnig und Unterschiede von Version 1 und 2 lassen sich damit
nicht Messen. Das kannst wohl nur Du machen, da nur Du die richtigen Codes hast und kennst!

Was ist also Deine Frage? :freak:
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
captain_hesse
Beiträge: 138
Registriert: 17.05.2009 18:55
Computerausstattung: Windows 7 Ultimate 64 Bit / AMD Phenom II 1090T, 6x3200 MHz / AMD HD-6850 / PureBasic 5.1 (x86) (x64)
Wohnort: Saarland

Re: Multicore Programmierung

Beitrag von captain_hesse »

Na ja im Grunde sind die Beispiele sehr ähnlich aufgebaut wie der Zuggenerator.
Hier ist also nun die Routine die, die Züge der weißen Figuren generiert

Code: Alles auswählen

zuggeneratorw:
figurenw=0
schachw=0
zz=0
rochade=0
epzug=0
schwarz_im_schach_so=0
schwarz_im_schach_zf=0
zz1=ti1
zz2=ti1
zz3=ti1
zz4=ti1
zz5=ti1
zz6=ti1
zz7=ti1
zz8=ti1
zz9=ti1
zz10=ti1
zz11=ti1
zz12=ti1
zz13=ti1
zz14=ti1
zz15=ti1
history=0


;generiere Bauernzüge
fn=310
While standort(fn)>-1
  If standort(fn)>0
    x=standort(fn)
    r1=x+12
    If hb(r1)=#freifeld 
      If r1<110 : Gosub eintragw : EndIf
      If r1>109
        If hb(r1)=#sk
        schachw=1
        schwarz_im_schach_so=x
        schwarz_im_schach_zf=r1
        EndIf
        zz+1
        zz12+1 
        sort.typ(zz12)\umwandlung[0]=x
        sort.typ(zz12)\umwandlung[1]=r1
        sort.typ(zz12)\umwandlungtyp=7
        
        zz+1
        zz12+1 
        sort.typ(zz12)\umwandlung[0]=x
        sort.typ(zz12)\umwandlung[1]=r1
        sort.typ(zz12)\umwandlungtyp=6
        
        zz+1
        zz12+1 
        sort.typ(zz12)\umwandlung[0]=x
        sort.typ(zz12)\umwandlung[1]=r1
        sort.typ(zz12)\umwandlungtyp=5
        
        zz+1
        zz12+1 
        sort.typ(zz12)\umwandlung[0]=x
        sort.typ(zz12)\umwandlung[1]=r1
        sort.typ(zz12)\umwandlungtyp=4
        
      EndIf
      r1=r1+12
      If x<46 And hb(r1)=#freifeld
        Gosub eintragw
      EndIf
    EndIf
    r1=x+11
    If hb(r1)<0
      If r1<110 : Gosub eintragw : EndIf
      If r1>109
        If hb(r1)=#sk
        schachw=1
        schwarz_im_schach_so=x
        schwarz_im_schach_zf=r1
        EndIf
        zz+1
        zz12+1 
        sort.typ(zz12)\umwandlung[0]=x
        sort.typ(zz12)\umwandlung[1]=r1
        sort.typ(zz12)\umwandlungtyp=7
        
        zz+1
        zz12+1 
        sort.typ(zz12)\umwandlung[0]=x
        sort.typ(zz12)\umwandlung[1]=r1
        sort.typ(zz12)\umwandlungtyp=6
        
        zz+1
        zz12+1 
        sort.typ(zz12)\umwandlung[0]=x
        sort.typ(zz12)\umwandlung[1]=r1
        sort.typ(zz12)\umwandlungtyp=5
        
        zz+1
        zz12+1 
        sort.typ(zz12)\umwandlung[0]=x
        sort.typ(zz12)\umwandlung[1]=r1
        sort.typ(zz12)\umwandlungtyp=4
      EndIf
    EndIf
    r1=x+13
    If hb(r1)<0
      If r1<110 : Gosub eintragw : EndIf
      If r1>109
        If hb(r1)=#sk
        schachw=1
        schwarz_im_schach_so=x
        schwarz_im_schach_zf=r1
        EndIf
        zz+1
        zz12+1 
        sort.typ(zz12)\umwandlung[0]=x
        sort.typ(zz12)\umwandlung[1]=r1
        sort.typ(zz12)\umwandlungtyp=7
        
        zz+1
        zz12+1 
        sort.typ(zz12)\umwandlung[0]=x
        sort.typ(zz12)\umwandlung[1]=r1
        sort.typ(zz12)\umwandlungtyp=6
        
        zz+1
        zz12+1 
        sort.typ(zz12)\umwandlung[0]=x
        sort.typ(zz12)\umwandlung[1]=r1
        sort.typ(zz12)\umwandlungtyp=5
        
        zz+1
        zz12+1 
        sort.typ(zz12)\umwandlung[0]=x
        sort.typ(zz12)\umwandlung[1]=r1
        sort.typ(zz12)\umwandlungtyp=4
      EndIf
    EndIf
  EndIf
  fn+1
Wend



;generiere Springerzüge
fn=350
While standort(fn)>-1 
  If standort(fn)>0
    x=standort(fn)
    figurenw+1
    Restore risp
    For x1=1 To 8
      Read.l r
      r1=x+r
      If hb(r1)=#freifeld
        Gosub eintragw
      EndIf
      If hb(r1)<0
        Gosub eintragw
      EndIf
    Next
  EndIf
  fn+1
Wend

;generiere läuferzüge
fn=360
While standort(fn)>-1
  If standort(fn)>0
    x=standort(fn)
    figurenw+1
    Restore rileu
    For x1=1 To 4
      Read.l r
      r1=x+r
      While hb(r1)=#freifeld
        Gosub eintragw
        r1=r1+r
      Wend
      If hb(r1)<0
        Gosub eintragw
      EndIf
    Next
  EndIf
  fn+1
Wend

;generiere Turmzüge
fn=320
While standort(fn)>-1
  If standort(fn)>0
    x=standort(fn)
    figurenw+1
    Restore ritu
    For x1=1 To 4
      Read.l r
      r1=x+r
      While hb(r1)=#freifeld
        Gosub eintragw
        r1=r1+r
      Wend
      If hb(r1)<0
        Gosub eintragw
      EndIf
    Next
  EndIf
  fn+1
Wend

;generiere Damenzüge
fn=330
While standort(fn)>-1
  If standort(fn)>0
    x=standort(fn)
    figurenw+1
    Restore rida
    For x1=1 To 8
      Read.l r
      r1=x+r
      While hb(r1)=#freifeld
        Gosub eintragw
        r1=r1+r
      Wend
      If hb(r1)<0
        Gosub eintragw
      EndIf
    Next
  EndIf
  fn+1
Wend


;generiere Königszüge
fn=340
While standort(fn)>-1
  If standort(fn)>0
    x=standort(fn)
    Restore riko
    For x1=1 To 8
      Read.l r
      r1=x+r
      If hb(r1)=#freifeld
        Gosub eintragw
      EndIf
      If hb(r1)<0
        Gosub eintragw
      EndIf
    Next
  EndIf
  fn+1
Wend

;generiere EP-Bauernzüge
If so-zf=24
  If hb(zf)=#sb
    If hb(zf-1)=#wb
      x=zf-1
      r1=zf+12
      zz+1
      zz14+1 
      sort.typ(zz14)\epzug[0]=x
      sort.typ(zz14)\epzug[1]=r1
      sort.typ(zz14)\epzugtyp=1
    EndIf
    If hb(zf+1)=#wb
      x=zf+1
      r1=zf+12
      zz+1
      zz14+1 
     sort.typ(zz14)\epzug[0]=x
     sort.typ(zz14)\epzug[1]=r1
     sort.typ(zz14)\epzugtyp=1
    EndIf
  EndIf
EndIf


;generiere Rocharden
If ti<=lev
If hb(30)=#wk 
  If krow(ti)=0 ; kleine rochade
    If hb(31)=#freifeld And hb(32)=#freifeld And hb(33)=#wt
      x=30
      r1=32
      zz+1
      zz13+1 
      sort.typ(zz13)\rochade[0]=x
      sort.typ(zz13)\rochade[1]=r1
      sort.typ(zz13)\rochadetyp=2
    EndIf
  EndIf
  If grow(ti)=0 ; grosse rochade
    If hb(29)=#freifeld And hb(28)=#freifeld And hb(27)=#freifeld And hb(26)=#wt
      x=30
      r1=28
      zz+1
      zz13+1 
      sort.typ(zz13)\rochade[0]=x
      sort.typ(zz13)\rochade[1]=r1
      sort.typ(zz13)\rochadetyp=3
     EndIf
  EndIf
EndIf
EndIf


anz(ti)=zz
zz1(ti)=zz1
zz2(ti)=zz2
zz3(ti)=zz3
zz4(ti)=zz4
zz5(ti)=zz5
zz6(ti)=zz6
zz7(ti)=zz7
zz8(ti)=zz8
zz9(ti)=zz9
zz10(ti)=zz10
zz11(ti)=zz11
zz12(ti)=zz12
zz13(ti)=zz13
zz14(ti)=zz14
zz15(ti)=zz15
Return
Der Zuggenerator wird von der Hauptschleife millionenfach aufgerufen und hier kann man nun sehen das zuerst die Bauernzüge dann die Springerzüge dann die Läuferzüge bis hin zu den Rochaden nacheinander erzeugt werden. Diese einzelnen Blocks würde ich nun gerne auf die (in meinem fall 4) Kerne der CPU verteilen so das sie parallel abgearbeitet werden. Nur wie schon gesagt mit den Methoden wie oben beschrieben läuft es halt nicht so wie ich es mir vorgestellt hatte. Na ja und wie du es ja auch schon gesagt hast ist der zeitaufwand für die verwaltung der Threads größer als die Zeit die der Thread braucht um abgearbeitet zu werden. Und nun suche ich halt nach alternativen Möglichkeiten um gewisse Programmteile zu parallelisieren. Und ich dachte mir das vieleicht hier jemand nen Tip oder eine Idee hat wie man sowas am besten angeht.
Windows 7 Ultimate 64 Bit / AMD Phenom II 1090T, 6x3200 MHz / AMD HD-6850 / PureBasic 5.1 (x86) (x64)
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Re: Multicore Programmierung

Beitrag von Kaeru Gaman »

also, ich würde drei Threads für die Zugberechnungen bauen, die mittels Globaler Variablen mit dem Hauptthread kommunizieren.
die Threads nicht immer extra starten, sondern intern parken wenn nichts zu tun ist,
z.B. indem du in der Thread-Procedure eine Schleife hast, die immer wieder Delay(20) ausführt bis ihre Berechnungen gebraucht werden.
damit hast du alle vier cores ausgenutzt, auf 2-core läufts auch ganz ok,
und vor allem brauchst du die threads nicht immer neu starten und kapseln, sondern nur einmal.
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
captain_hesse
Beiträge: 138
Registriert: 17.05.2009 18:55
Computerausstattung: Windows 7 Ultimate 64 Bit / AMD Phenom II 1090T, 6x3200 MHz / AMD HD-6850 / PureBasic 5.1 (x86) (x64)
Wohnort: Saarland

Re: Multicore Programmierung

Beitrag von captain_hesse »

Hallo Kaeru
So wie du es beschreibst habe ich es auch schon versucht siehe Beispiel 2 nur die Anzahl der Threads ist anders und statt einer Warteschleife habe ich Semaphore benutzt da eine warteschleife mit delay die reaktionszeit eines Threads extrem nach unten schraubt, selbst bei einem delay(1) und ohne delay hat man immer 100% CPU auslastung. Aber damit hast du mich auf eine Idee gebracht ich werde das mal mit PauseThread() anstatt mit WaitSemaphore() Testen.
Windows 7 Ultimate 64 Bit / AMD Phenom II 1090T, 6x3200 MHz / AMD HD-6850 / PureBasic 5.1 (x86) (x64)
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Re: Multicore Programmierung

Beitrag von Kaeru Gaman »

das Problem dabei wäre wohl, dass der thread irgendwo mitten in der Berechnung stecken könnte.
also, der müsste wohl schon in einer Seitenbedingung geparkt werden, bevor er pausiert wird.
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
captain_hesse
Beiträge: 138
Registriert: 17.05.2009 18:55
Computerausstattung: Windows 7 Ultimate 64 Bit / AMD Phenom II 1090T, 6x3200 MHz / AMD HD-6850 / PureBasic 5.1 (x86) (x64)
Wohnort: Saarland

Re: Multicore Programmierung

Beitrag von captain_hesse »

nee das geht schon, der Thread gibt ein Signal an die Hauptschleife das er fertig ist und hält sich dann selbst an bis er mit ResumeThread() wieder gestartet wird.

Code: Alles auswählen

Procedure s1(t1)
  Repeat
  PauseThread(t1)
  For x=1 To 10
    a=1
    liste(a,x)
  Next
  SignalSemaphore(sp1_stop)
  ForEver
EndProcedure 
nur leider ist es immer noch langsamer als mit einem CPU-Kern /:->
Windows 7 Ultimate 64 Bit / AMD Phenom II 1090T, 6x3200 MHz / AMD HD-6850 / PureBasic 5.1 (x86) (x64)
Benutzeravatar
captain_hesse
Beiträge: 138
Registriert: 17.05.2009 18:55
Computerausstattung: Windows 7 Ultimate 64 Bit / AMD Phenom II 1090T, 6x3200 MHz / AMD HD-6850 / PureBasic 5.1 (x86) (x64)
Wohnort: Saarland

Re: Multicore Programmierung

Beitrag von captain_hesse »

Hmm
Ich muß mich korrigieren
nee das geht schon, der Thread gibt ein Signal an die Hauptschleife das er fertig ist und hält sich dann selbst an bis er mit ResumeThread() wieder gestartet wird.

Code: Alles auswählen

Procedure s1(t1)
Repeat
PauseThread(t1)
For x=1 To 10
a=1
liste(a,x)
Next
SignalSemaphore(sp1_stop)
ForEver
EndProcedure 
nur leider ist es immer noch langsamer als mit einem CPU-Kern /:->
das geht doch nicht es läuft fehlerhaft es geht nur mit WaitSemaphore() so wie es aussieht kann sich ein Thread auf diese weise nicht selbst anhalten.

Na ja wie dem auch sei, jedenfalls werde ich weitere Experimente damit machen und meine Erfahrungen dann hier posten.
Windows 7 Ultimate 64 Bit / AMD Phenom II 1090T, 6x3200 MHz / AMD HD-6850 / PureBasic 5.1 (x86) (x64)
Antworten