Threading questions/problems
Re: Threading questions
Thanks all :)
vdecampo, what is PUSH/POP the stack? Yes, your version is more than twice as fast, I guess, mainly because you moved two subs into one? And what do you mean by large overhead?
Thanks fxm for your example, I'm still thinking if I will use ptr's or shared variable's. I need to do some testing if it really is such a big slow down. Also thanks for the topic link, I will go through it when I find some more time.
Thanks for clearing that up SARG, really good to know that I don't have to mutex array access if I don't access the same elements. That's why my program worked fine but the counter was off.
vdecampo, what is PUSH/POP the stack? Yes, your version is more than twice as fast, I guess, mainly because you moved two subs into one? And what do you mean by large overhead?
Thanks fxm for your example, I'm still thinking if I will use ptr's or shared variable's. I need to do some testing if it really is such a big slow down. Also thanks for the topic link, I will go through it when I find some more time.
Thanks for clearing that up SARG, really good to know that I don't have to mutex array access if I don't access the same elements. That's why my program worked fine but the counter was off.
Re: Threading questions
When a sub or a function is called, parameters and return adress are stored (push) on the stack and at the end of the call they are removed (pop).Provoni wrote:vdecampo, what is PUSH/POP the stack? Yes, your version is more than twice as fast, I guess, mainly because you moved two subs into one? And what do you mean by large overhead?
This process consumes processor time so if it's possible to avoid them the program runs faster.
Here the overhead is that "unnecessary" time added to your code (search of prime).
No problem you are welcome.Provoni wrote: Thanks for clearing that up SARG, really good to know that I don't have to mutex array access if I don't access the same elements. That's why my program worked fine but the counter was off.
Re: Threading questions
By “user made flags” I’m assuming that you mean a shared variable used to direct the thread procedure to return, ending the thread. FWIW under Windows you can use TerminateThread to force a thread to exit, but note in the Remarks section the potentially adverse effects of doing so. I tested the code below under Windows XP SP3, compiled with 0.90.1, -gen gas and -gen gcc.Provoni wrote:Is it possible to end one of these threads without user made flags?
Code: Select all
#include "windows.bi"
sub Thread( userdata as any ptr )
do
print ".";
sleep 100
loop
end sub
dim as any ptr fbThread = threadcreate( @Thread )
dim as HANDLE hThread = *cast(HANDLE ptr,fbThread)
sleep
''----------------------------------------------
'' The Windows TerminateThread function returns
'' non-zero for success or zero for failure.
''----------------------------------------------
print TerminateThread( hThread, 0 )
sleep
/'
From the FreeBASIC 0.90.1 source \rtlib\fb_private_thread.h:
struct _FBTHREAD {
#if defined HOST_DOS
int id;
#elif defined HOST_UNIX
pthread_t id;
#elif defined HOST_WIN32
HANDLE id;
#elif defined HOST_XBOX
HANDLE id;
#else
#error Unexpected target
#endif
FB_THREADPROC proc;
void *param;
void *opaque;
};
From FreeBASIC 0.90.1 source \rtlib\win32\thread_core.c:
FBCALL FBTHREAD *fb_ThreadCreate( FB_THREADPROC proc, void *param, int stack_size )
{
FBTHREAD *thread = (FBTHREAD *)malloc( sizeof(FBTHREAD) );
if( thread == NULL )
return NULL;
thread->proc = proc;
thread->param = param;
#ifdef HOST_MINGW
/* Note: _beginthreadex()'s last parameter cannot be NULL,
or else the function fails on Windows 9x */
unsigned int thrdaddr;
thread->id = (HANDLE)_beginthreadex( NULL, stack_size, threadproc, (void *)thread, 0, &thrdaddr );
#else
DWORD dwThreadId;
thread->id = CreateThread( NULL, stack_size, threadproc, (void*)thread, 0, &dwThreadId );
#endif
if( thread->id == NULL ) {
free( thread );
thread = NULL;
}
return thread;
}
'/
Re: Threading questions
Thanks MichaelW.
I've run into some problems with the threading in one of my programs. I'm trying to thread a sub which is responsible for drawing stuff on the screen with line and draw string. I made sure to put all shared variables inside a mutex.
Screenlock and unlock seem not to work as intended with 2 threads or more.
Also my program kept locking up until I remarked this line: if x1<dxbound1 and y1<dybound1 and x1>dxbound2 and y1>dybound2 then. None of these variables are shared, they are local to the sub.
I still get lockups on start, showing a white screen. If it doesn't lockup on the first batch of threadcalls it doesn't crash anymore for as long as I run it.
Thanks
I've run into some problems with the threading in one of my programs. I'm trying to thread a sub which is responsible for drawing stuff on the screen with line and draw string. I made sure to put all shared variables inside a mutex.
Screenlock and unlock seem not to work as intended with 2 threads or more.
Also my program kept locking up until I remarked this line: if x1<dxbound1 and y1<dybound1 and x1>dxbound2 and y1>dybound2 then. None of these variables are shared, they are local to the sub.
I still get lockups on start, showing a white screen. If it doesn't lockup on the first batch of threadcalls it doesn't crash anymore for as long as I run it.
Thanks
Re: Threading questions/problems
This code shows the problem. Some threads just ignore screenlock, as well as random lockups.
Code: Select all
declare sub MYTHREAD(byval hey as any ptr)
dim shared as integer threads=4 'number of threads
dim shared as byte inc
dim as any ptr thread(threads)
dim as longint i,j
screenres 600,600,32
color rgb(200,200,200)
for i=1 to 10000
screenlock
cls
for j=1 to threads 'create threads
thread(j)=threadcreate(@MYTHREAD,@inc)
next j
for j=1 to threads 'wait for threads to end
threadwait(thread(j))
next
inc=0
screenunlock
next i
beep
sleep
sub MYTHREAD(byval hey as any ptr)
dim as any ptr mylock=mutexcreate()
mutexlock mylock
inc=inc+1
dim as byte i=inc
mutexunlock mylock
select case i
case 1
line(0,0)-(600,150),,bf
case 2
line(0,150)-(600,300),,bf
case 3
line(0,300)-(600,450),,bf
case 4
line(0,450)-(600,600),,bf
end select
end sub
Re: Threading questions/problems
The FB graphics library is not yet thread safe, unfortunately. That means it cannot safely be used used from multiple threads at the same time. It's supposed to be fixed someday, but it's not easy.
Re: Threading questions/problems
Hey dkl, thanks for letting me know.
Re: Threading questions/problems
Another remark:
- Your mutex structure is inefficient because each thread works with its own local mutex!
- You must define a shared mutex at the main body level before start the threads execution:
dim shared as any ptr mylock
mylock=mutexcreate()
- Your mutex structure is inefficient because each thread works with its own local mutex!
- You must define a shared mutex at the main body level before start the threads execution:
dim shared as any ptr mylock
mylock=mutexcreate()
Re: Threading questions/problems
Yes, fbgfx is not thread safe, and this may induce hangs, but when this runs, [ScreenLock...ScreenUnlock] seems to be well taken into account versus the drawing from the threads!Provoni wrote:This code shows the problem. Some threads just ignore screenlock, as well as random lockups.
Test this program (yours slightly modified) without and with [ScreenLock...ScreenUnlock]:
Code: Select all
declare sub MYTHREAD(byval hey as any ptr)
dim shared as integer threads=4 'number of threads
dim shared as byte inc
dim as any ptr thread(threads)
dim as longint j
screenres 600,600,32
color rgb(200,200,200)
dim shared as any ptr mylock
mylock=mutexcreate()
do
' screenlock
cls
sleep 100
for j=1 to threads 'create threads
thread(j)=threadcreate(@MYTHREAD,@inc)
next j
for j=1 to threads 'wait for threads to end
threadwait(thread(j))
next
inc=0
sleep 25
' screenunlock
loop while inkey = ""
beep
sleep
sub MYTHREAD(byval hey as any ptr)
mutexlock mylock
inc=inc+1
dim as byte i=inc
mutexunlock mylock
select case i
case 1
line(0,300)-(600,300)
case 2
line(0,0)-(600,600)
case 3
line(300,0)-(300,600)
case 4
line(600,0)-(0,600)
end select
end sub
Re: Threading questions/problems
Hey fxm,
Thanks for your remarks, I made the mutex global now.
I experimented with your using of sleep in my program, it works fine until my program draws slower - due to heavy workload - than the sleep induced framerate.
I'm going to work around the problem for now, I'll start by moving all possible calculations outside of the drawing routine. Which will increase memory usage just a bit but that's okay. And then I'll start threading my calculation sub routine's.
Thanks for your remarks, I made the mutex global now.
I experimented with your using of sleep in my program, it works fine until my program draws slower - due to heavy workload - than the sleep induced framerate.
I'm going to work around the problem for now, I'll start by moving all possible calculations outside of the drawing routine. Which will increase memory usage just a bit but that's okay. And then I'll start threading my calculation sub routine's.
Re: Threading questions/problems
Hey all,
Another question,
I have a shared array(x,y) to which I need full access in every thread. Is it possible to create a copy, or an exclusive temporary of that array for each thread? Or will I have to add another dimension, array(threads,x,y)? Or do I need to use pointers to achieve this?
Thanks
Another question,
I have a shared array(x,y) to which I need full access in every thread. Is it possible to create a copy, or an exclusive temporary of that array for each thread? Or will I have to add another dimension, array(threads,x,y)? Or do I need to use pointers to achieve this?
Thanks
-
- Posts: 8586
- Joined: May 28, 2005 3:28
- Contact:
Re: Threading questions/problems
The key is to control the array accesses via mutex.
http://www.freebasic.net/wiki/wikka.php ... gThreading
Joshy
http://www.freebasic.net/wiki/wikka.php ... gThreading
Joshy
Re: Threading questions/problems
We can group in a TYPE the thread code and all the necessary data to the threads for working:
- the thread procedure declared as static member procedure,
- the shared data declared as static member data,
- the specific data declared as non-static member data,
and pass at each thread its dedicated instance pointer.
See my previous example modified as following:
Remark: 'sleep 1' in the [mutexlock..mutexunlock] block is put just to highlight the importance of a mutex when the threads use a shared variable with a read/write access (put in comment the two lines 'mutexlock .mylock' and 'mutexunlock .mylock' and see the result!).
- the thread procedure declared as static member procedure,
- the shared data declared as static member data,
- the specific data declared as non-static member data,
and pass at each thread its dedicated instance pointer.
See my previous example modified as following:
Code: Select all
'----- thread type definition -----
type thread
dim as any ptr pthread
dim as integer colour
static as byte inc
static as any ptr mylock
declare static sub mythread (byval hey as any ptr)
end type
dim as byte thread.inc
dim as any ptr thread.mylock
static sub thread.mythread (byval p as any ptr)
dim as thread ptr pt = p
with *pt
mutexlock .mylock
.inc =. inc + 1
sleep 1
dim as byte i = .inc
mutexunlock .mylock
select case i
case 1
line(0,300)-(600,300), .colour
case 2
line(0,0)-(600,600), .colour
case 3
line(300,0)-(300,600), .colour
case 4
line(600,0)-(0,600), .colour
end select
end with
end sub
'----- Main program -----
screenres 600, 600, 8
dim as thread threads(0 To 3)
thread.mylock = mutexcreate()
do
screenlock
cls
sleep 100
for i as integer = lbound(threads) to ubound(threads) 'create threads
threads(i).colour = 11 + i
threads(i).pthread = threadcreate(@thread.mythread, @threads(i))
next i
for i as integer = lbound(threads) to ubound(threads) 'wait for threads to end
threadwait(threads(i).pthread)
next
thread.inc = 0
sleep 25
screenunlock
loop while inkey = ""
mutexdestroy thread.mylock
sleep
Re: Threading questions/problems
D.J.Peters and fxm, you'll have to excuse me because I asked a stupid question. Somehow I didn't pop up in my mind that I could just create a local version of my array in each thread.
I have some questions about your example fxm,
First of all, thanks for making me aware of with-end with, I can really put that to good use.
I don't understand the concept of static variables, you also made the sub static? This is very new for me and the FBWiki has allot to say about the subject. I'm not sure if I really need to use this. I also noticed you declared a sub in a UDT?
I have some questions about your example fxm,
First of all, thanks for making me aware of with-end with, I can really put that to good use.
I don't understand the concept of static variables, you also made the sub static? This is very new for me and the FBWiki has allot to say about the subject. I'm not sure if I really need to use this. I also noticed you declared a sub in a UDT?