- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
At first, I'm sorry for my pour English even I don' know it is right or wrong to question here. But only thing I need is some help.
Now I'm developing stand alone MFC program. So I want to use OpenMP. Then I realized it has some problem or me.
Here is my Test codes. (VC++ 2010 MFC Application - Dialog based Project)
void COpenMPWinDlg::OnBnClickedButton1()
{
// TODO
CString sString;
int i=0;
#pragma omp parallel for
for(i=0; i < 10; i++)
{
sString.Format(_T("%d, thread id = %d"), i, omp_get_thread_num());
//m_List.AddString(sString);
OutputDebugString(sString + "\r\n");
}
}
I expected serial number not 0 to 9 (2,3,5,1 ~ 9)
But the result is belows,
0, thread id = 0
1, thread id = 0
1, thread id = 0
2, thread id = 0
7, thread id = 2
8, thread id = 3
8, thread id = 3
4, thread id = 1
9, thread id = 3
5, thread id = 1
I tried it console program in VC++ 2010 then it is working correctly.
But I need it in MFC application. Please help. thank you.
- Tags:
- Parallel Computing
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
As far as I understand your question you are expecting linearly increasing loop counter variable i=0, i=1,1=2,1=3 etc... In your case different threads are executing omp region in random order which is chosen probably by the Windows scheduler/dispatcher.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Parallel code, a loop in this example, run in parallel (to the extent of your thread pool size). The parallel part runs concurrently, but not necessarily in sequence.
Your code has an error in that sString is place outside the scope of the parallel region and thus defaults to shared. All threads will attempt to use this string without regard to the other threads. You should also get into the habit of using "for(int i=0;..." to assure that i is private. Note, while OpenMP will automatically make the loop control variable private of a parallel for (or omp for in parallel region), it will not automatically make private loop control variables used on interior loops inside the parallel region.
If you require the output sequence to be in the same order as appears in the serial implementation, then you have two options:
1) Use an output array, not a non-thread safe std::container such as a list, which may get corrupted with concurrent AddString, and in any event will get appended in thread entry order and not necessarily loop index order. The parallel loop would execute in any order with each thread placing its output into the output array. Then after the parallel loop, you would have a serial section performing the in-order output. This procedure would not be practical for high iteration counts.
2) Write your own sequencer. This may also require a schedule modifier to the parallel for to set the chunk size to 1. This would cause thread picking order to be in sequence, however the time of thread completing the computation section and arriving at your output section is not controllable. The usual way to sequence the output then would be with use of a volatile or atomic variable that states the sequence number of the next output. Then threads reaching the output section would loop waiting for the sequence number of the next output to become the value of its index. At which point the thread exits the wait loop, writes its output, increments the next output sequence number, then reaches the bottom of your parallel for loop (and presumably loops back up for another iteration). There are some trade-offs here as the threads are non-productive while they are awaiting their turn to write its output. There are more complicated ways to correct for this.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
void COpenMPWinDlg::OnBnClickedButton1() { // TODO CString sString[10]; // same size as loop count #pragma omp parallel for for(int i=0; i < 10; i++) { // Do work here // ... // Now output to in-sequence output array sString.Format(_T("%d, thread id = %d"), i, omp_get_thread_num()); } // after parallel loop, serialy handle output (in sequence) for(int i=0; i < 10; i++) { OutputDebugString(sString + "\r\n"); } } void COpenMPWinDlg::OnBnClickedButton1() { // TODO volatile int OutputSequence = 0; #pragma omp parallel for schedule(dynamic,1) for(int i=0; i < BigLoopCount; i++) { // Do work here // ... // Now buile output CString sString; sString.Format(_T("%d, thread id = %d"), i, omp_get_thread_num()); // wait my turn for(;i < OutputSequence;) Sleep(0); OutputDebugString(sString + "\r\n"); OutputSequence = i+1; // indicate next ouput sequence number } }
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thank you so much. Now I got the concept. The key was put CString in parellel for. It is really helpful.
Have a good day.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page