getting started with threads

classic Classic list List threaded Threaded
29 messages Options
12
Reply | Threaded
Open this post in threaded view
|

getting started with threads

David Emerson
I am getting started with threads (linux/cthreads) and I'm very happy so
far, but unsure of the best way to tackle my situation.

I have a program that needs to perform about 10,000 independent tasks,
which usually involve waiting for I/O; thus it makes sense to use
several threads so that some waiting can be done in parallel. I thought
I'd try it with 10 threads.

When a thread completes its task, I'd like it to simply request a new
task from the queue. The best way I could think to do this was to have
a task assignment function (which accesses a global variable and
returns a task id, marking it as pending.)

But how can I prevent race conditions? If threads X and Y happen to call
the task assignment function at the same time, it seems to me that they
could both be assigned to the same task. I know that this is a problem
which has been addressed at great length in the computer science
world ... so what's the easiest way for me to address it here and now?


While writing this message it dawned on me that I probably need an event
loop (I'm writing a console app) which will, e.g., sleep for 1 second
and then check on the status of each thread's work. Then the main loop
can assign a new task by starting a new thread, whenever it finds one
that is finished. That puts the assignment task back in the main loop
where there is no race condition.

Do I even need to send this message? It would be nice to get a little
input and see if I'm on the right track :)

Cheers,
David

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: getting started with threads

Mark Emerson
Nice to see you posted this.  Love, Dad

On Thursday 17 September 2009 06:07:48 pm David Emerson wrote:

> I am getting started with threads (linux/cthreads) and I'm very happy so
> far, but unsure of the best way to tackle my situation.
>
> I have a program that needs to perform about 10,000 independent tasks,
> which usually involve waiting for I/O; thus it makes sense to use
> several threads so that some waiting can be done in parallel. I thought
> I'd try it with 10 threads.
>
> When a thread completes its task, I'd like it to simply request a new
> task from the queue. The best way I could think to do this was to have
> a task assignment function (which accesses a global variable and
> returns a task id, marking it as pending.)
>
> But how can I prevent race conditions? If threads X and Y happen to call
> the task assignment function at the same time, it seems to me that they
> could both be assigned to the same task. I know that this is a problem
> which has been addressed at great length in the computer science
> world ... so what's the easiest way for me to address it here and now?
>
>
> While writing this message it dawned on me that I probably need an event
> loop (I'm writing a console app) which will, e.g., sleep for 1 second
> and then check on the status of each thread's work. Then the main loop
> can assign a new task by starting a new thread, whenever it finds one
> that is finished. That puts the assignment task back in the main loop
> where there is no race condition.
>
> Do I even need to send this message? It would be nice to get a little
> input and see if I'm on the right track :)
>
> Cheers,
> David
>
> _______________________________________________
> fpc-pascal maillist  -  [hidden email]
> http://lists.freepascal.org/mailman/listinfo/fpc-pascal



_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

apology

Mark Emerson
In reply to this post by David Emerson
I apologize for accidentally posting a personal note to this list.

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: getting started with threads

Tobias Giesen-2
In reply to this post by David Emerson
> But how can I prevent race conditions? If threads X and Y happen to
> call the task assignment function at the same time, it seems to me
> that they could both be assigned to the same task.

Use for example the cross-platform implementations of
Enter/LeaveCriticalSection. Like this:

EnterCriticalSection(MyCritVar);
try
  DoStuff
finally
  LeaveCriticalSection(MyCritVar);
end;

> Then the main loop can assign a new task by starting a new thread,
> whenever it finds one > that is finished.

Also possible but not easier. Threads should not be started or
stopped for each task, instead they should wait for an event telling
them to continue with the next task. For example using SetEvent /
ResetEvent as well as:

{$ifdef win32}
WaitForSingleObject(ContinueEvent,INFINITE);
{$else}
RTLEventWaitFor(ContinueEvent);
{$endif}

Cheers,
Tobias


_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Re: getting started with threads

Luca Olivetti-2
En/na Tobias Giesen ha escrit:

> Also possible but not easier. Threads should not be started or
> stopped for each task, instead they should wait for an event telling
> them to continue with the next task. For example using SetEvent /
> ResetEvent as well as:
>
> {$ifdef win32}
> WaitForSingleObject(ContinueEvent,INFINITE);
> {$else}
> RTLEventWaitFor(ContinueEvent);
> {$endif}

There are some cross-platform synchronization classes in syncobjs

http://www.freepascal.org/docs-html/fcl/syncobjs/index.html

Bye
--
Luca

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: getting started with threads

Vincent Snijders-2
In reply to this post by David Emerson
David Emerson schreef:
> I am getting started with threads (linux/cthreads) and I'm very happy so
> far, but unsure of the best way to tackle my situation.
>
> I have a program that needs to perform about 10,000 independent tasks,
> which usually involve waiting for I/O; thus it makes sense to use
> several threads so that some waiting can be done in parallel. I thought
> I'd try it with 10 threads.

Maybe you can use MTProcs unit: http://wiki.lazarus.freepascal.org/Parallel_procedures

You don't need to worry about assigning tasks anymore.

Vincent
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Re: getting started with threads

Graeme Geldenhuys-4
In reply to this post by Luca Olivetti-2
Luca Olivetti het geskryf:
>
> There are some cross-platform synchronization classes in syncobjs
>
> http://www.freepascal.org/docs-html/fcl/syncobjs/index.html

And I'm working on cross-platform semaphore classes / methods because
the current ones in FPC are totally useless.


Regards,
  - Graeme -

--
fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal
http://opensoft.homeip.net/fpgui/

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Re: getting started with threads

Jonas Maebe-2

On 18 Sep 2009, at 10:12, Graeme Geldenhuys wrote:

> And I'm working on cross-platform semaphore classes / methods because
> the current ones in FPC are totally useless.

I guess you mean that there aren't any :)


Jonas
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Re: getting started with threads

Graeme Geldenhuys-4
Jonas Maebe het geskryf:
>
> I guess you mean that there aren't any :)

True and False. :)  It was recommended to me that I use the methods
directly from the thread manager, then later it was not recommended.
Plus the methods available from the thread manager doesn't support
initial max values for semaphores.

End result - totally useless. :)


Regards,
  - Graeme -

--
fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal
http://opensoft.homeip.net/fpgui/

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Re: getting started with threads

Florian Klämpfl
Graeme Geldenhuys schrieb:
> Jonas Maebe het geskryf:
>> I guess you mean that there aren't any :)
>
> True and False. :)  It was recommended to me that I use the methods
> directly from the thread manager, then later it was not recommended.
> Plus the methods available from the thread manager doesn't support
> initial max values for semaphores.
>
> End result - totally useless. :)

Hope you find a good cross platform solution :)
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Re: getting started with threads

Jonas Maebe-2
In reply to this post by Graeme Geldenhuys-4

On 18 Sep 2009, at 11:42, Graeme Geldenhuys wrote:

> Jonas Maebe het geskryf:
>>
>> I guess you mean that there aren't any :)
>
> True and False. :)  It was recommended to me that I use the methods
> directly from the thread manager, then later it was not recommended.

It's because there is no cross-platform guarantee for any of the  
thread manager routines (i.c., the semaphore ones are only implemented  
for Unix platforms).


Jonas
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Re: getting started with threads

Martin Frb
just a question:

Should semaphores be on the thread manager?

because imho they are not realy thread related? They can be used by
threads, but they have lot's of other uses. Even communication between
processes of different applications. They are usually grouped together
with other IPC like msg-queues and shared-mem.

my 2 cent

Martin

Jonas Maebe wrote:

>
> On 18 Sep 2009, at 11:42, Graeme Geldenhuys wrote:
>
>> Jonas Maebe het geskryf:
>>>
>>> I guess you mean that there aren't any :)
>>
>> True and False. :)  It was recommended to me that I use the methods
>> directly from the thread manager, then later it was not recommended.
>
> It's because there is no cross-platform guarantee for any of the
> thread manager routines (i.c., the semaphore ones are only implemented
> for Unix platforms).
>
>
> Jonas
> _______________________________________________
> fpc-pascal maillist  -  [hidden email]
> http://lists.freepascal.org/mailman/listinfo/fpc-pascal

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Re: getting started with threads

Jonas Maebe-2

On 18 Sep 2009, at 12:12, Martin wrote:

> Should semaphores be on the thread manager?
>
> because imho they are not realy thread related? They can be used by  
> threads, but they have lot's of other uses. Even communication  
> between processes of different applications. They are usually  
> grouped together with other IPC like msg-queues and shared-mem.

These are unrelated things. As mentioned before, the thread manager is  
not for public use, so whether or not it has hooks for semaphores is  
irrelevant w.r.t. what semaphores could theoretically be used for.


Jonas
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Re: getting started with threads

Graeme Geldenhuys-4
In reply to this post by Florian Klämpfl
Florian Klaempfl het geskryf:
>
> Hope you find a good cross platform solution :)

So far I have single interface for create/destroy/lock/unlock of
semaphores for Windows, Linux, *BSD. The latter two is actually for all
unix with posix systems. So no more IFDEF's and specific uses clauses
units in my higher level code.

I only have access to the platforms I mentioned above. Other developers
with access to other platforms can implement the remaining
implementations, or raise an exception if no implementation exists - to
warn the end-user developer.


Regards,
  - Graeme -

--
fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal
http://opensoft.homeip.net/fpgui/

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: getting started with threads

Dariusz Mazur
In reply to this post by David Emerson
David Emerson pisze:

> I am getting started with threads (linux/cthreads) and I'm very happy so
> far, but unsure of the best way to tackle my situation.
>
> I have a program that needs to perform about 10,000 independent tasks,
> which usually involve waiting for I/O; thus it makes sense to use
> several threads so that some waiting can be done in parallel. I thought
> I'd try it with 10 threads.
>
> When a thread completes its task, I'd like it to simply request a new
> task from the queue. The best way I could think to do this was to have
> a task assignment function (which accesses a global variable and
> returns a task id, marking it as pending.)
>
> But how can I prevent race conditions? If threads X and Y happen to call
> the task assignment function at the same time, it seems to me that they
> could both be assigned to the same task. I know that this is a problem
> which has been addressed at great length in the computer science
> world ... so what's the easiest way for me to address it here and now?
>
>
> While writing this message it dawned on me that I probably need an event
> loop (I'm writing a console app) which will, e.g., sleep for 1 second
> and then check on the status of each thread's work. Then the main loop
> can assign a new task by starting a new thread, whenever it finds one
> that is finished. That puts the assignment task back in the main loop
> where there is no race condition.
>  

You need FIFO queue for multiple consumer. Each task can be assigned to
them.
You can use ordinal tThreadList but it rather slow.

I use own lockfree FIFO http://www.emadar.com/fpc/lockfree.htm to
distribute task between threads
its much faster and well scaling on multicore.




--
  Darek




_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: getting started with threads

Jonas Maebe-2

On 18 Sep 2009, at 16:24, Dariusz Mazur wrote:

> I use own lockfree FIFO http://www.emadar.com/fpc/lockfree.htm to  
> distribute task between threads
> its much faster and well scaling on multicore.

Note that it won't work as is on non-x86 machines, because it's  
missing memory barriers (and I think that you may actually need memory  
barriers on x86 too). Atomic operations are not memory barriers by  
themselves, and the fact that you perform an atomic operation does not  
mean that afterwards all cpu's will immediately see this new value.


Jonas
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: getting started with threads

Florian Klämpfl
Jonas Maebe schrieb:

>
> On 18 Sep 2009, at 16:24, Dariusz Mazur wrote:
>
>> I use own lockfree FIFO http://www.emadar.com/fpc/lockfree.htm to
>> distribute task between threads
>> its much faster and well scaling on multicore.
>
> Note that it won't work as is on non-x86 machines, because it's missing
> memory barriers (and I think that you may actually need memory barriers
> on x86 too). Atomic operations are not memory barriers by themselves,
> and the fact that you perform an atomic operation does not mean that
> afterwards all cpu's will immediately see this new value.

On x86 they are.
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: getting started with threads

Dariusz Mazur
In reply to this post by Jonas Maebe-2
Jonas Maebe pisze:

>
> On 18 Sep 2009, at 16:24, Dariusz Mazur wrote:
>
>> I use own lockfree FIFO http://www.emadar.com/fpc/lockfree.htm to
>> distribute task between threads
>> its much faster and well scaling on multicore.
>
> Note that it won't work as is on non-x86 machines, because it's
> missing memory barriers (and I think that you may actually need memory
> barriers on x86 too). Atomic operations are not memory barriers by
> themselves, and the fact that you perform an atomic operation does not
> mean that afterwards all cpu's will immediately see this new value.
I don't know other machines. On x86 used atomic operation, as Intel
said,  all needed cache are resolved.
I've made very stress test on several computers. it works good.
Algorithm is very simple, need only 32bit CAS, thus implement it is
possible on most platforms.
One thing is needed: multiplatform threadswich.

I use sleep(0) ,but its not best solution (I think).


--
  Darek




_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: getting started with threads

Jonas Maebe-2

On 18 Sep 2009, at 21:30, Dariusz Mazur wrote:

>>
>> On 18 Sep 2009, at 16:24, Dariusz Mazur wrote:
>>
>>> I use own lockfree FIFO http://www.emadar.com/fpc/lockfree.htm to  
>>> distribute task between threads
>>> its much faster and well scaling on multicore.
>>
>> Note that it won't work as is on non-x86 machines, because it's  
>> missing memory barriers (and I think that you may actually need  
>> memory barriers on x86 too). Atomic operations are not memory  
>> barriers by themselves, and the fact that you perform an atomic  
>> operation does not mean that afterwards all cpu's will immediately  
>> see this new value.
> I don't know other machines. On x86 used atomic operation, as Intel  
> said,  all needed cache are resolved.
> I've made very stress test on several computers. it works good.

At least on PowerPC it will fail (and I guess on SPARC as well).

> Algorithm is very simple, need only 32bit CAS, thus implement it is  
> possible on most platforms.
> One thing is needed: multiplatform threadswich.
>
> I use sleep(0) ,but its not best solution (I think).

At least on Mac OS X that will not do anything. There's a procedure  
called "ThreadSwitch" in the interface of the system unit though. At  
least for Unix platforms it will work if cthreads is used.


Jonas
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: getting started with threads

Dariusz Mazur
Jonas Maebe pisze:

>
> On 18 Sep 2009, at 21:30, Dariusz Mazur wrote:
>
>>>
>>> On 18 Sep 2009, at 16:24, Dariusz Mazur wrote:
>>>
>>>> I use own lockfree FIFO http://www.emadar.com/fpc/lockfree.htm to
>>>> distribute task between threads
>>>> its much faster and well scaling on multicore.
>>>
>>> Note that it won't work as is on non-x86 machines, because it's
>>> missing memory barriers (and I think that you may actually need
>>> memory barriers on x86 too). Atomic operations are not memory
>>> barriers by themselves, and the fact that you perform an atomic
>>> operation does not mean that afterwards all cpu's will immediately
>>> see this new value.
>> I don't know other machines. On x86 used atomic operation, as Intel
>> said,  all needed cache are resolved.
>> I've made very stress test on several computers. it works good.
>
> At least on PowerPC it will fail (and I guess on SPARC as well).
I don't say, that this will work on other than x86. I only test on Intel
and AMD.

>
>> Algorithm is very simple, need only 32bit CAS, thus implement it is
>> possible on most platforms.
>> One thing is needed: multiplatform threadswich.
>>
>> I use sleep(0) ,but its not best solution (I think).
>
> At least on Mac OS X that will not do anything. There's a procedure
> called "ThreadSwitch" in the interface of the system unit though. At
> least for Unix platforms it will work if cthreads is used.

I sow it, but not test.
Seems enough to me.

But is this optimal solution:

procedure SysThreadSwitch;
begin
       Sleep(0);
end;

    WinThreadManager.ThreadSwitch           :=@SysThreadSwitch;

procedure ThreadSwitch;
begin
  CurrentTM.ThreadSwitch;
end;

We have 2 unnecessary  invoke function. Can compiler optimize this? Or
maybe better do ThreadSwitch and SysThreadSwitch inlined.



--
  Darek




_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
12