Page 1 of 1

Tasks and threads

Posted: Tue May 03, 2011 7:46 pm
by eriansa
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 ;-))

Code: Select all

#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()


Re: Tasks and threads

Posted: Thu May 05, 2011 9:51 am
by eriansa
Nobody?

Re: Tasks and threads

Posted: Thu May 05, 2011 10:41 am
by cxAlex
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

Re: Tasks and threads

Posted: Thu May 05, 2011 10:57 pm
by eriansa
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???

Re: Tasks and threads

Posted: Fri May 06, 2011 11:01 am
by Trond
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.