|
-
April 27th, 2011, 12:41 PM
#1
Multithreading
Hello,
I have a question and hope to get some helps or approaches from here.
My program has two child threads, thread1 and thread2 spawned from the main thread. when a button from the main thread is clicked, it checks user's selections on three check boxes. The checks can be in any combination, but they always be executed in sequence.
Thread1 is in charge of running three heavy calculations and thread2 is in charge of displaying results immediately after each calculation to the GUI. I have both threads created in main in the suspended states. When the button is clicked, thread1 starts doing his jobs. Once thread1 finishes his first job, it resumes thread2 to update the results to the screen. In the mean while, thread2 continues to do his second job.
The question I have is how do I put thread2 to pause until thread1 finishes his second job, then thread2 can update the results to screen, then continue one in this fashion. I do not want to use busy wait loop, because it will eat up lots of cpu time. What is the best approach here in this case?
Moreover, once thread1 finishes all his tasks, user can input different parameters and restart the calculation again with different selections.
-
April 27th, 2011, 01:33 PM
#2
Re: Multithreading
Victor Nijegorodov
-
April 30th, 2011, 03:14 PM
#3
Re: Multithreading
 Originally Posted by ktxn
Hello,
I have a question and hope to get some helps or approaches from here.
My program has two child threads, thread1 and thread2 spawned from the main thread. when a button from the main thread is clicked, it checks user's selections on three check boxes. The checks can be in any combination, but they always be executed in sequence.
Thread1 is in charge of running three heavy calculations and thread2 is in charge of displaying results immediately after each calculation to the GUI. I have both threads created in main in the suspended states. When the button is clicked, thread1 starts doing his jobs. Once thread1 finishes his first job, it resumes thread2 to update the results to the screen. In the mean while, thread2 continues to do his second job.
The question I have is how do I put thread2 to pause until thread1 finishes his second job, then thread2 can update the results to screen, then continue one in this fashion. I do not want to use busy wait loop, because it will eat up lots of cpu time. What is the best approach here in this case?
Moreover, once thread1 finishes all his tasks, user can input different parameters and restart the calculation again with different selections.
Create an event and wait on the event in thread2. When thread1 finishes its work, set the event.
-
May 2nd, 2011, 05:38 PM
#4
Re: Multithreading
I have used Event objects to alternatively lock/unlock threads. Child thread handles the calculation while main thread handles the GUI update. The way I did was: I have 2 events created in main. When the program runs, and the STart button is pressed. STart handler function opens two events, creates a child thread and set event to the Event1. ThreadFunc() is a thread function that runs from child thread. STart() also calls Output() to update GUI right after the call to create the child thread.
ThreadFunc() has a loop. Inside the loop, WaitForSingleObject() is called at first to check for Event1.
It then does some calculation, saves the results to an array, resets Event1 and then sets Event2. Output() works similar to ThreadFunc(). It reads the data from the array generated from the child thread, reset Event2 and then set Event1.
This code works, but the GUI is unresponsive. I used FLTK tool kit for the GUI. If any of you use FLTK please give some advice, or you think there is a better approach then using Event objects, please give me some helps.
Thanks,
-
May 4th, 2011, 01:06 AM
#5
Re: Multithreading
Frankly, all the scheme seems overcomplicated. As for me, the only one worker thread is needed - thread1. And I hardly can see a reason for having thread2, as typically main GUI thread does this kind of things alright, of course in case all the GUI data is already cooked by worker thread.
So, this is how I would go with all this. There is some global memory containing worker thread configuration parameters along with the data container needed for output results. The memory access is synchronized by critical section. The worker thread starts normal way (there's no need to have it suspended) and starts to wait on "GetToWork" event indefinitely. The main GUI thread in button click handler reads the check boxes and fills the worker configuration data. After that it signals GetToWork and returns. This way GUI thread remains unblocked. Worker thread after waking up on GetToWork starts doing its jobs sequentially phase by phase, and on finishing every phase it sends* a dedicated window message to GUI window reporting particular phase data got ready. GUI thread renders the data (I hope much faster than the other data get ready, otherwise some anti-jamming mechanism has to be introduced**). This happens until worker thread completes the job. After that it gets to wait on GetToWork event until next job coming.
I think most of the multi-threaded GUI apps operate this way.
* Should be posts.
** In fact, window message queue already is a sort of anti-jamming mechanism, as all the messages get processed in a row but not simultaneously. And therefore, the worker thread just should use PostMessage for notification purpose and don't try to access the already processed GUI data.
Last edited by Igor Vartanov; May 5th, 2011 at 12:15 AM.
Best regards,
Igor
-
May 4th, 2011, 08:38 PM
#6
Re: Multithreading
I largely agree with Igor, except for one very important clarification (which I think he intended, but I'm sure he will tell us):
 Originally Posted by Igor Vartanov
... Worker thread after waking up on GetToWork starts doing its jobs sequentially phase by phase, and on finishing every phase it sends a dedicated window message to GUI window reporting particular phase data got ready. ...
The worker thread should post the message, not send it. In other words, the worker thread should use PostMessage to post the message, and not SendMessage to send the message.
The reason is that SendMessage will require the worker thread to wait for a response from the GUI thread before the worker can continue execution, whereas PostMessage does not. In the best case, this will cause significant delays, since the GUI thread cannot respond until there's a thread context switch, and the worker thread connot recognize the response until there's a thread context swithc back to the worker (at least in a single core machine that's true). In the worst case, there can be a deadlock, if (for example) the GUI thread decides that it needs something from the worker thread before it can respond to the SendMessage. Such a deadlock would occur even in a multi-core machine.
Mike
-
May 5th, 2011, 12:10 AM
#7
Re: Multithreading
Mike, you're right, that 'send' was just to give an idea. In the same post below you can find my mentioning of PostMessage.
Best regards,
Igor
-
May 9th, 2011, 02:10 PM
#8
Re: Multithreading
I have coded like this:
main thread updates the GUI, child thread performs calculation. Main thread has a loop checking if each data point is available for output using while loop as
for (i.. 30000)
{
lock
while(data[i] != -1) Sleep(10);
output
unlock
}
but the overall running time of the worker thread runs on 1 core takes 3 times more than without using multithread, and even running it on a dual core. Any suggestion/explaination is really appreciated.
Thanks
-
May 9th, 2011, 02:17 PM
#9
Re: Multithreading
Remove all the "locks" and Sleep() from the GUI thread!
Victor Nijegorodov
-
May 9th, 2011, 02:48 PM
#10
Re: Multithreading
I removed all locks and sleep, it still takes about the same time. What is the difference of running multithreaded program on single core vs on dual/multiple cores?
Thanks
-
May 9th, 2011, 02:55 PM
#11
Re: Multithreading
 Originally Posted by ktxn
...
but the overall running time of the worker thread runs on 1 core takes 3 times more than without using multithread, ...
Sounds like a bad design or/and bad implementation...
Victor Nijegorodov
-
May 9th, 2011, 03:09 PM
#12
Re: Multithreading
How to use postmessage() and how to make it more efficient? Will postmessage() give a better implementation in term of execution time.? Thanks for any suggestion.
-
May 9th, 2011, 03:14 PM
#13
Re: Multithreading
I already gave you a link in the post#2.
Victor Nijegorodov
-
May 9th, 2011, 03:27 PM
#14
Re: Multithreading
 Originally Posted by ktxn
Code:
for (i.. 30000)
{
lock
while(data[i] != -1) Sleep(10);
output
unlock
}
but the overall running time of the worker thread runs on 1 core takes 3 times more than without using multithread, and even running it on a dual core. Any suggestion/explaination is really appreciated.
Remove all of this code, which polls for results in the main GUI thread (very bad). Your main GUI thread should react to the messages that Igor mentioned, which are posted from the worker thread. Something like this:
Code:
// in worker thread
// when something is finished in the worker, which
// warrants an update to the gui
::PostMessage(hWndGuiThread, MYSPECIALMESSAGE, (WPARAM) result1, (LPARAM) result2);
// ... where result1 and result2 are coded message contents from the worker thread, if needed
// in main GUI thread
LRESULT OnMySpecialMessage( WPARAM wParam, LPARAM lParam)
{
// decode wParam and lParam
output
return 0L;
}
This architecture will avoid polling, and will probably exhibit increased performance and decreased times. If not, then the issue might be related to "false sharing".
Mike
-
May 10th, 2011, 03:39 AM
#15
Re: Multithreading
 Originally Posted by ktxn
Main thread has a loop checking if each data point is available for output using while loop as
 Originally Posted by ViktorN
Sounds like a bad design...
Normally (except really trivial cases) multithreaded architecture builds on top of message/event notification mechanism. This way data processing occurs only when it's really needed. Locking mechanisms are acceptable in GUI, but should be implemented most effective way having in mind minimal possible GUI blocking. The least blocking schema is: worker thread fills the data block, signals data ready and never touches it anymore.
 Originally Posted by ktxn
What is the difference of running multithreaded program on single core vs on dual/multiple cores?
On a single core hardware Windows kernel does preemptive execution when each thread one by one is given with a time slice, during which only one thread possesses the CPU core. On a multicore system threads appear distributed among the cores available at a time, and this way it may happen that few threads of the same app get executed simultaneously.
Best regards,
Igor
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|