Do you guys think following code can be optimised. It looks ok, but perhaps there are better ways to spread tasks evenly over different threads. I want to implement multi-core support in a real-time audio application.
(surely the delay()'s and so on are only for demonstrational purposes )
#NrOfThreads=3
#NrOfTasks=50
Structure MyThread
ThreadId.l
MutexId.l
SemaphoreId.l
EndStructure
Global Dim arrThreads.MyThread(#NrOfThreads-1)
OpenConsole()
Procedure MyThread(i)
Repeat
PrintN(" -Waiting Thread->" + Str(i))
WaitSemaphore(arrThreads(i)\SemaphoreId)
LockMutex(arrThreads(i)\MutexId)
PrintN(" -Running Thread->"+str(i))
For j=1 to 10
delay(50)
Next
UnlockMutex(arrThreads(i)\Mutexid)
ForEver
EndProcedure
For i = 0 to #NrOfThreads-1
arrThreads(i)\SemaphoreId=CreateSemaphore()
arrThreads(i)\MutexId=CreateMutex()
arrThreads(i)\ThreadId=CreateThread(@MyThread(),i)
Next
PrintN("Waiting in Main")
NrOfTasks=#NrOfTasks
delay(500)
Repeat
For i= 0 to #NrOfThreads-1
if NrOfTasks
if TryLockMutex(arrThreads(i)\MutexId)
PrintN("Remaining tasks->"+str(NrOfTasks))
NrOfTasks-1
UnlockMutex(arrThreads(i)\MutexId)
PrintN(" -Signalling Thread->"+str(i) )
SignalSemaphore(arrThreads(i)\SemaphoreId)
delay(10)
EndIf
EndIf
Next
Until NrOfTasks=0
Printn("All tasks ended, press any key to close")
Repeat
delay(10)
until Inkey()
I think I've coded a Include that can do what you need, a background JobProcessor, with a variable amount of threads, priority management and many other Features. I'm using this Include in many of my projects, it's very stable and fast: Link to german forum and download: http://www.purebasic.fr/german/viewtopic.php?t=19188
cxAlex wrote:I think I've coded a Include that can do what you need, a background JobProcessor, with a variable amount of threads, priority management and many other Features. I'm using this Include in many of my projects, it's very stable and fast: Link to german forum and download: http://www.purebasic.fr/german/viewtopic.php?t=19188
Greets, Alex
I have implemented your great code into my Audio-app since a couple of months. It works OK, but I am not getting the best performance. (You need to know that my app. works with Asio low latency, with bufferswitches up to 5 ms.)
This results in audio drop-outs.
What I am looking for is the fastest way to spread tasks evenly over the available cores.
If I understand well : PB's Semaphore is Win->WaitFor(Single)(Multiple)Object_/SetEvent_ and PB's Mutex is in fact a Win-> Semaphore.
The question is : are there other implementations possible to speed things up???
For latency-sensitive tasks like this I'd keep the threads running as long as the song is playing. With your current implementation they could potentially be put to sleep on the semaphore and then waken up right in the middle of the song again and again, which would lower performance dramatically. Instead leave them spinning in an empty loop when there is no task available. (Maybe leave this as an option - more cpu use and lower latency vs. less cpu and higher latency.)
For distributing the tasks you have two choices, a central queue vs one queue per thread. One queue per thread avoids many threads competing for locking the task queue at the same time, however, distributing the tasks evenly is much harder. You may end up with one cpu overwhelmed and another starving.