I\'m trying to learn the basics of parallel computing, but I\'m running into an issue on my computer. Take a look at my code below. Basically, I want to print out the line &
As already explained, the assumption that printf()
is atomic and won't mangle your output whereas std::cout::operator<<()
is not and will mess things up if fundamentally wrong.
However, there is still a (tiny) part of "truth" in this, but at a different level. Let me give you an example:
If I try an OpenMP "Hello world" C-style, that might give this:
printf( "Hello from thread %d of %d\n",
omp_get_thread_num(),
omp_get_num_threads() );
The same one C++-style could look like this:
std::cout << "Hello from thread " << omp_get_thread_num()
<< " of " << omp_get_num_threads()
<< std::endl;
And the essential difference between the two is that for printf()
, I only call the printing method once, with a fully prepared output string, while the C++-style one will call std::cout::operator<<()
5 times, with only bits and pieces of lines that may or may not be sent to the standard output.
Internally, anything can happen and I won't try to commit on any sort of behaviour. But at least by using printf()
here, I increase my chances of a clean output, even if I cannot guaranty it.
Here is a full 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;
}
Which on my Linux laptop 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 carefully, you can see that none of the individual calls to std::cout::operator<<()
is split, but each new call is an opportunity for the various threads to races each-other, and to get the output mangled.
So again, telling that printf()
is atomic and won't mess things up is wrong, but simply, for a complex output string, it is less likely to be mangled than with std::cout
.
Sorry, your professor's mistaken. You need to leverage mutual exclusion or some other barriers in order to guarantee uninterrupted use of a shared resource (which in this case is the STDOUT
output file).
Mixed output is potential expected behavior regardless of printf
or std::cout::operator<<()
. The differences in behavior you see are subtle differences in the execution duration of each, due to their differing design. You should expect this behavior in either case.
I just don't understand why it would be working for everyone else.
It's not. Be a hero to your class and explain how it works and how to fix it. Tell them SO sends their love. :)