Thread Pool
Verfasst: 27.02.2012 16:08
Da ja inzwischen eigentlich jeder Rechner mehrere Rechenkerne hat bin ich gerade dabei mal zu schauen ob ich nicht einige meiner Entwicklungen etwas beschleunigen kann.
Problem dabei ist dass die meisten Aufgaben nicht lange genug dauern damit sich das Erstellen eines Thread so richtig lohnt oder man hat so viele hat dass es Unsinn wäre für jeden einen Thread zu erstellen.
Um diese Probleme zu umgehen entstand jetzt dieser Quellcode der es erleichtern soll mehr Rechenkerne zu nutzen in dem mehre Threads als Gruppe angelegt werden können die dann nacheinander alle an sie geschickten Aufgaben abarbeiten.
Vielleicht kann es ja noch jemand außer mir brauchen oder hat sogar noch andere gute Ideen für so etwas.
Update: Kleine Code Änderung + Kommentare
Problem dabei ist dass die meisten Aufgaben nicht lange genug dauern damit sich das Erstellen eines Thread so richtig lohnt oder man hat so viele hat dass es Unsinn wäre für jeden einen Thread zu erstellen.
Um diese Probleme zu umgehen entstand jetzt dieser Quellcode der es erleichtern soll mehr Rechenkerne zu nutzen in dem mehre Threads als Gruppe angelegt werden können die dann nacheinander alle an sie geschickten Aufgaben abarbeiten.
Vielleicht kann es ja noch jemand außer mir brauchen oder hat sogar noch andere gute Ideen für so etwas.
Update: Kleine Code Änderung + Kommentare
Code: Alles auswählen
; -------------------------------------------------------------------------------
; -------------------------------------------------------------------------------
; ThreadPool.pb
; 28-02-2012
; Christian+
; -------------------------------------------------------------------------------
; -------------------------------------------------------------------------------
EnableExplicit
; -------------------------------------------------------------------------------
; RunThreadData Structure
; -------------------------------------------------------------------------------
; Speichert alle vom Thread Pool benötigten Daten.
; -------------------------------------------------------------------------------
Structure RunThreadData
*ThreadProcedure
*Parameter
Semaphore.i
EndStructure
; -------------------------------------------------------------------------------
; ThreadPoolData Structure
; -------------------------------------------------------------------------------
; Speichert alle von den Thread Pool Threads benötigten Daten.
; -------------------------------------------------------------------------------
Structure ThreadPoolData
Semaphore.i
Mutex.i
List Tasks.RunThreadData()
List Threads.i()
EndStructure
; -------------------------------------------------------------------------------
; RunThread(*ThreadPool.ThreadPoolData)
; -------------------------------------------------------------------------------
; Die vom Thread Pool als Threads verwendete Procedure.
; -------------------------------------------------------------------------------
; *ThreadPool.ThreadPoolData
; = Zeiger auf den Thread Pool (= die ThreadPoolData Strcuture).
; -------------------------------------------------------------------------------
Procedure RunThread(*ThreadPool.ThreadPoolData)
Protected *ThreadProcedure, *Parameter
Protected Semaphore.i
Repeat
WaitSemaphore(*ThreadPool\Semaphore)
LockMutex(*ThreadPool\Mutex)
FirstElement(*ThreadPool\Tasks())
*ThreadProcedure = *ThreadPool\Tasks()\ThreadProcedure
*Parameter = *ThreadPool\Tasks()\Parameter
Semaphore = *ThreadPool\Tasks()\Semaphore
DeleteElement(*ThreadPool\Tasks())
UnlockMutex(*ThreadPool\Mutex)
If *ThreadProcedure = 0 And *Parameter = 0
Break
EndIf
CallFunctionFast(*ThreadProcedure, *Parameter)
If Semaphore
SignalSemaphore(Semaphore)
EndIf
ForEver
EndProcedure
; -------------------------------------------------------------------------------
; Run(*ThreadPool.ThreadPoolData, *ThreadProcedure, *Parameter, Semaphore.i = 0)
; -------------------------------------------------------------------------------
; Übergibt die Angegebene Methode an den Thread Pool zum im Hintergrund
; abarbeiten. Ähnlich wie CreateThread() die Proceduren unterliegen
; auch den gleichen Einschränkungen.
; -------------------------------------------------------------------------------
; *ThreadPool.ThreadPoolData
; = Zeiger auf den Thread Pool (= die ThreadPoolData Strcuture).
; *ThreadProcedure
; = Zeiger auf die Procedure die als Thread ausgeführt werden soll.
; *Parameter
; = Zeiger auf Daten wird beim Ausführen der Procedure als Parameter an
; die Procedure übergeben.
; Semaphore.i = 0
; = Optionales Semaphore für das ein SignalSemaphore ausgeführt wird wen
; die Procedure ausgeführt wurde.
; -------------------------------------------------------------------------------
Procedure Run(*ThreadPool.ThreadPoolData, *ThreadProcedure, *Parameter, Semaphore.i = 0)
LockMutex(*ThreadPool\Mutex)
LastElement(*ThreadPool\Tasks())
AddElement(*ThreadPool\Tasks())
*ThreadPool\Tasks()\ThreadProcedure = *ThreadProcedure
*ThreadPool\Tasks()\Parameter = *Parameter
*ThreadPool\Tasks()\Semaphore = Semaphore
UnlockMutex(*ThreadPool\Mutex)
SignalSemaphore(*ThreadPool\Semaphore)
EndProcedure
; -------------------------------------------------------------------------------
; CreateThreadPool(*ThreadPool.ThreadPoolData, Number.i)
; -------------------------------------------------------------------------------
; Legt einen neuen ThreadPool an.
; -------------------------------------------------------------------------------
; *ThreadPool.ThreadPoolData
; = Zeiger auf den Thread Pool (= die ThreadPoolData Strcuture).
; Number
; = Anzahl an Thread die verwendet werden soll.
; -------------------------------------------------------------------------------
Procedure CreateThreadPool(*ThreadPool.ThreadPoolData, Number.i)
Protected i.i
*ThreadPool\Semaphore = CreateSemaphore()
*ThreadPool\Mutex = CreateMutex()
For i = 1 To Number
AddElement(*ThreadPool\Threads())
*ThreadPool\Threads() = CreateThread(@RunThread(), *ThreadPool)
Next
EndProcedure
; -------------------------------------------------------------------------------
; CloseThreadPool(*ThreadPool.ThreadPoolData)
; -------------------------------------------------------------------------------
; Beendet einen ThreadPool und wartet dabei bis die Warteschlage abgearbeitet ist.
; -------------------------------------------------------------------------------
; *ThreadPool.ThreadPoolData
; = Zeiger auf den Thread Pool (= die ThreadPoolData Strcuture).
; -------------------------------------------------------------------------------
Procedure CloseThreadPool(*ThreadPool.ThreadPoolData)
Protected i.i, Size.i
Size = ListSize(*ThreadPool\Threads())
For i = 1 To Size
Run(*ThreadPool, 0, 0)
Next
For i = 1 To Size
WaitThread(*ThreadPool\Threads())
DeleteElement(*ThreadPool\Threads(), 1)
Next
EndProcedure
; -------------------------------------------------------------------------------
; -------------------------------------------------------------------------------
; -------------------------------------------------------------------------------
; Beispiel:
; (Nicht sehr sinnvoll aber es sollte ja möglichst kurz sein.)
; -------------------------------------------------------------------------------
Procedure Thread(*Parameters)
Protected i.i
For i = 0 To 1000000
Next
EndProcedure
Define i.i, Time.i
OpenConsole()
Time = ElapsedMilliseconds()
Define ThreadPool.ThreadPoolData
;Thread Pool mit 4 Threads anlegen
CreateThreadPool(@ThreadPool, 4)
;50 Aufgaben an den Thread Pool senden
For i = 0 To 50
Run(ThreadPool, @Thread(), 0)
Next
;Thread Pool schließen und Warten bis alle abgearbeitet sind
CloseThreadPool(ThreadPool)
time = ElapsedMilliseconds() - time
PrintN("Mit Threads: " + Str(time) + "ms")
Time.i = ElapsedMilliseconds()
For i = 0 To 50
Thread(0)
Next
time = ElapsedMilliseconds() - time
PrintN("Ohne Threads: " + Str(time) + "ms")
Input()
End