PFor - Paralleles For

Übersicht BlitzMax, BlitzMax NG Codearchiv & Module

Neue Antwort erstellen

BtbN

Betreff: PFor - Paralleles For

BeitragDi, Dez 01, 2009 18:11
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich hab vorhin mal eine kleine Funktion geschrieben, welche es ermöglicht, eine For-Schleifen artige Struktur beliebig zu parallelisieren, erstmal hier der Code, kann einfach importiert werden:

BlitzMax: [AUSKLAPPEN]
SuperStrict

Import BRL.Threads
Import BRL.LinkedList

?Threaded
Private
Type TForPart
Field _from:Long
Field _to:Long
Field _step:Int

Method ToString:String()
Return "~qFor i = "+_from+" To "+_to+" Step "+_step+"~q"
EndMethod
EndType

Type TForSheduler
Field mut:TMutex
Field list:TList
Field curLink:TLink

Method New()
mut = TMutex.Create()
list = New TList
curLink = Null
EndMethod

Method Init(pfrom:Long, pto:Long, pstep:Int, psize:Int)
mut.Lock()
list.Clear()

Local pstart:Long = pfrom
While pfrom <= pto
Local part:TForPart = New TForPart

part._from = pfrom + ((pfrom-pstart) Mod pstep)
If part._from > pto Then Exit
part._to = pfrom + psize - 1
If part._to > pto Then part._to = pto
part._step = pstep

list.AddLast(part)
DebugLog "Added Part: "+part.ToString()

pfrom :+ psize
Wend

curLink = list.FirstLink()

mut.Unlock()
EndMethod

Method Reset()
mut.Lock()
curLink = list.FirstLink()
mut.Unlock()
EndMethod

Method GetPart:TForPart()
Local r:TForPart = Null

mut.Lock()
If curLink <> Null Then
r = TForPart(curLink.Value())
curLink = curLink.NextLink()
EndIf
mut.Unlock()

Return r
EndMethod
EndType

Type TCont
Field func(i:Long)
Field shed:TForSheduler
EndType
Public
?

Function PForLeg(_from:Long, _to:Long, _step:Int, func(i:Long), _size:Int = 5, threadCount:Int = 4)
If _to < _from Or _step < 1 Or _size < 1 Or threadCount < 1 Then Throw "Invalid Arguments"

Local j:Long = _from
While j <= _to
func(j)
j :+ _step
Wend
EndFunction

Function PFor(_from:Long, _to:Long, _step:Int, func(i:Long), _size:Int = 5, threadCount:Int = 4)
If _to < _from Or _step < 1 Or _size < 1 Or threadCount < 1 Then Throw "Invalid Arguments"
?Not Threaded
PForLeg(_from, _to, _step, func, _size, threadCount)
?Threaded
If threadCount = 1 Then
PForLeg(_from, _to, _step, func, _size, threadCount)
Return
EndIf

Local shed:TForSheduler = New TForSheduler
shed.Init(_from, _to, _step, _size)

Function itf:Object(par:Object)
Local o:TCont = TCont(par)
Assert o, "Internal Sheduler Error"
Local shed:TForSheduler = o.shed
Local func(i:Long) = o.func

Local part:TForPart = shed.GetPart()
While part <> Null
Local k:Long = part._from
While k <= part._to
func(k)
k :+ part._step
Wend
part = shed.GetPart()
Wend

Return Null
EndFunction

Local threads:TThread[] = New TThread[threadCount]
For Local j:Int = 0 Until threadCount
Local o:TCont = New TCont
o.func = func
o.shed = shed
threads[j] = TThread.Create(itf, o)
Next
For Local t:TThread = EachIn threads
t.Wait()
Next
?
EndFunction



Hier ein simples Verwendungs-Beispiel:

BlitzMax: [AUSKLAPPEN]
SuperStrict

Framework BRL.Blitz

Import "pfor.bmx"


Function DoFor(i:Long)
WriteStdout("Value "+i+" in Thread "+CurrentThread().ToString()+"~n")
Delay 100
EndFunction

Local t:Int = MilliSecs()
PFor(1,50, 1, DoFor, 2)
t = MilliSecs()-t

WriteStdout("Took "+(t)+"ms~n~n")

t=MilliSecs()
PForLeg(1,50, 1, DoFor, 2)
t = MilliSecs()-t
WriteStdout("Took "+(t)+"ms~n~n")

Hier sieht man auch schön, dass er weniger zeit für die zeitfressende aufgabe braucht, wenn man es parallel ausführt. Bei echter last sähe das natürlich ein wenig anders aus, aber solang noch eine CPU frei ist, ist auch das kein Thema.

Die funktion, die man der PFor funktion übergibt, MUSS komplett thread-safe sein, sonst fliegt einem das ding um die Ohren.

Ich bitte um tests, da ich mir vorallem beim aufteilungs-algo der for-loop noch unsicher bin, ob er in allen Fällen korrekt arbeitet.


Mfg


Edit: Hab das ganze als Modul verpackt, ist auf meinem GIT zu finden.

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Codearchiv & Module

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group