Parallel computing - mixed up output?

I am trying to learn the basics of parallel computing, but I ran into a problem on my computer. Take a look at my code below. Basically, I want to print the string "Hello World!". for every core of my computer. My computer has four cores, so it should print this line four times. If I used the used commented line 'cout' instead of the line 'printf', the output would be all mixed up. This is because the "\ n" escape command is executed separately from "Hello World!", So new line output will occur randomly. The "printf" line is a solution to this problem because the line is executed immediately (does not break into parts, such as the "cout" line). However, when I use 'printf', my output is still mixed up as if I were using 'cout'. I have no idea why he is doing this. I tried the exact same code on another computer and it works great. This is only my computer, which continues to intercept the output with "printf". I emailed my CS professor about this, and he has no idea why this is done on my computer. I know that I configured OpenMP correctly on my computer. Does anyone with experience in parallel computing know why this is happening on my computer?

#include <omp.h> #include <stdio.h> #include <iostream> #include <stdlib.h> using namespace std; int main() { #pragma omp parallel { printf("Hello World!\n"); //cout << "Hello World!\n" << endl; } return 0; } 

To show what I'm talking about, here is the output when I ran the above code on my computer:

Hi wo

Hello World!

RLD!

Hello World!

+6
source share
2 answers

Sorry, your professor was wrong. You need to use mutual exclusion or some other barriers to ensure continued use of the shared resource (which in this case is the output file STDOUT ).

Mixed output is the potential expected behavior regardless of printf or std::cout::operator<<() . The differences in the behaviors that you see are subtle differences in the duration of each due to their different designs. You should expect this behavior anyway.

I just don’t understand why it will work for everyone else.

This is not true. Be the hero of your class and explain how it works and how to fix it. Tell them they send their love. :)

+6
source

As already explained, the assumption that printf() is atomic and will not cripple your result, whereas std::cout::operator<<() will not and will spoil things if it is fundamentally wrong.

However, there is still a (tiny) part of the "truth", but on a different level. Let me give you an example:

If I try to use the OpenMP C-style "Hello world", which can give the following:

 printf( "Hello from thread %d of %d\n", omp_get_thread_num(), omp_get_num_threads() ); 

The same C ++ style might look like this:

 std::cout << "Hello from thread " << omp_get_thread_num() << " of " << omp_get_num_threads() << std::endl; 

And the significant difference between them is that for printf() I call the print method only once with a fully prepared output string, and the C ++ style calls std::cout::operator<<() 5 times, moreover only bits and pieces of lines that may or may not be sent to standard output. Everything can happen inside, and I will not try to take any action. But at least by using printf() here, I increase my chances of a clean output, even if I cannot guarantee it.

Here is a complete example:

 #include <iostream> #include <stdio.h> #include <omp.h> int main() { #pragma omp parallel printf( "Hello from thread %d of %d with printf()\n", omp_get_thread_num(), omp_get_num_threads() ); printf( "*** outside of parallel region ***\n" ); #pragma omp parallel std::cout << "Hello from thread " << omp_get_thread_num() << " of " << omp_get_num_threads() << " with std::cout" << std::endl; return 0; } 

What on my laptop Linux gives me (GCC 5.2):

 ~/tmp$ g++ -fopenmp stdout.cc ~/tmp$ ./a.out Hello from thread 3 of 4 with printf() Hello from thread 0 of 4 with printf() Hello from thread 2 of 4 with printf() Hello from thread 1 of 4 with printf() *** outside of parallel region *** Hello from thread Hello from thread Hello from thread Hello from thread 1 of 4 with std::cout23 of 4 with std::cout of 4 with std::cout 0 of 4 with std::cout ~/tmp$ 

If you look closely, you will see that none of the individual calls to std::cout::operator<<() is broken, but each new call is an opportunity for different threads to race each other and to get the result.

And again, saying that printf() is atomic and will not mess things up, this is wrong, but just for a complex output string it is less likely to be distorted than with std::cout .

+4
source

All Articles