Je ne sais pas si ça convient à ton cas mais en faisant du multi-thread, j'obtiens de bonnes performances.
1 thread = 343ms
2 thread = 188ms
Je n'ai pas pu tester avec plus de thread, j'ai qu'un double coeurs, mais le code qui suit s'adapte automatiquement.
A compiler en mode ThreadSafe !
Fichier include :Code : Tout sélectionner
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Windows ;{
Global Total_CPU = Val(GetEnvironmentVariable("NUMBER_OF_PROCESSORS"))-1
;}
CompilerCase #PB_OS_Linux ;{
grep = RunProgram("grep","-c processor /proc/cpuinfo","./",#PB_Program_Open|#PB_Program_Read)
If grep
Sortie$ + ReadProgramString(grep) + Chr(13)
Global Total_CPU = Val(Sortie$)-1
EndIf
;}
CompilerEndSelect
Global wait_thread = CreateSemaphore()
Global mutex = CreateMutex()
Macro P_For(variable, start)
For variable=start+core
EndMacro
Macro P_Next(variable)
variable+Total_CPU
Next variable
EndMacro
Structure ParallelFor
thread.i
core.i
parent.i
wait.b
return_procedure.i
EndStructure
Global NewList Working_Threads.ParallelFor()
Prototype ProtoLoop(core, parametre)
Global Loop.ProtoLoop
Procedure WorkerThread(parametre)
thread_id = Working_Threads()\thread
core = Working_Threads()\core
wait = Working_Threads()\wait
SignalSemaphore(wait_thread)
Resultat = Loop(core, parametre)
;Fin du thread
LockMutex(mutex)
ForEach Working_Threads()
If Working_Threads()\thread = thread_id
If wait = #False
;efface le thread
DeleteElement(Working_Threads())
Break
Else
;procedure return
If Working_Threads()\return_procedure = 0
Working_Threads()\return_procedure = Resultat
Break
EndIf
EndIf
EndIf
Next
UnlockMutex(mutex)
EndProcedure
Procedure ParallelFor(id, wait.b, *procedure_ptr, parametre)
Loop.ProtoLoop = *procedure_ptr
LockMutex(mutex)
For x=0 To Total_CPU
AddElement(Working_Threads())
Working_Threads()\core = x
Working_Threads()\thread = CreateThread(@WorkerThread(), parametre)
Working_Threads()\parent = id
Working_Threads()\wait = wait
If x=0
first_thread = Working_Threads()\thread
EndIf
WaitSemaphore(wait_thread)
Next x
UnlockMutex(mutex)
If wait = #True
For x=0 To Total_CPU
WaitThread(first_thread+x)
Next x
;procedurereturn et efface les threads
LockMutex(mutex)
ForEach Working_Threads()
If Working_Threads()\parent = id
Resultat = Working_Threads()\return_procedure
If Resultat
return_procedure = Resultat
EndIf
DeleteElement(Working_Threads())
EndIf
Next
UnlockMutex(mutex)
ProcedureReturn return_procedure
Else
ProcedureReturn id
EndIf
EndProcedure
Procedure IsParallelFor(id)
LockMutex(mutex)
ForEach Working_Threads()
If Working_Threads()\parent = id
ProcedureReturn 1
EndIf
Next
UnlockMutex(mutex)
EndProcedure
Procedure KillParallelFor(id)
LockMutex(mutex)
ForEach Working_Threads()
If Working_Threads()\parent = id
KillThread(Working_Threads()\thread)
DeleteElement(Working_Threads())
EndIf
Next
UnlockMutex(mutex)
EndProcedure
Procedure PauseParallelFor(id)
LockMutex(mutex)
ForEach Working_Threads()
If Working_Threads()\parent = id
PauseThread(Working_Threads()\thread)
EndIf
Next
UnlockMutex(mutex)
EndProcedure
Procedure ResumeParallelFor(id)
LockMutex(mutex)
ForEach Working_Threads()
If Working_Threads()\parent = id
ResumeThread(Working_Threads()\thread)
EndIf
Next
UnlockMutex(mutex)
EndProcedure
Exemple :
Code : Tout sélectionner
IncludeFile "Multicore.pbi"
Structure zbuffer
*depth_buffer.i
w.l
h.l
EndStructure
ProcedureDLL.i zbuffer(w.l, h.l, mFar.f)
*zb.zbuffer = AllocateMemory(SizeOf(zbuffer))
*zb\depth_buffer = AllocateMemory( w * h * 4 )
*zb\w = w
*zb\h = h
FillMemory(*zb\depth_buffer , MemorySize(*zb\depth_buffer), mFar, #PB_Long)
ProcedureReturn *zb
EndProcedure
ProcedureDLL zbuffer_write(*zb.zbuffer)
For i = 0 To 50
For y = 0 To 480-1
For x = 0 To 640
If x=>0 And x < *zb\w And y=>0 And y < *zb\h
PokeF(*zb\depth_buffer + (x*4) + *zb\w * (y*4), Random(1500))
EndIf
Next
Next
Next
EndProcedure
ProcedureDLL zbuffer_write_multi(core, *zb.zbuffer)
P_For(i, 0) To 50
For y=0 To 480-1
For x=0 To 640
If x=>0 And x < *zb\w And y=>0 And y < *zb\h
PokeF(*zb\depth_buffer + (x*4) + *zb\w * (y*4), Random(1500))
EndIf
Next x
Next y
P_Next(i)
EndProcedure
Buffer = zbuffer(640,480,1500)
;Single thread
A = ElapsedMilliseconds()
zbuffer_write(Buffer)
B = ElapsedMilliseconds()
WriteTime = B-A
MessageRequester("Single thread", Str(WriteTime))
;Multi thread
A = ElapsedMilliseconds()
ParallelFor(0, #True, @zbuffer_write_multi(), Buffer)
B = ElapsedMilliseconds()
WriteTime = B-A
MessageRequester("Multi thread", Str(WriteTime))