5

I am using openmp and my program looks like as follows:

\#pragma omp parallel for

for(x = 0, y = 0, x < 5, x++, y++)

     function(x, y, fp);

void function(int x , int y, FILE* fp);
{
   fprintf(fp, "(%d, %d)\n", x y);
}

I want that the content of file as

(0, 0)
(2, 2)
(1, 1)
(3, 3)
(4, 4)

The ordering doesn't matter but the coordinates x, y should be in order, ie the program should not generate something like (2, 3). Is this behavior always guaranteed? I am using gcc compiler on linux.

MByD
  • 135,866
  • 28
  • 264
  • 277
quartz
  • 747
  • 9
  • 26
  • I doubt that it's guaranteed, but if you want to be sure, you could issue `write()` system calls directly, which *are* guaranteed to be atomic (on Posix). – Kerrek SB May 12 '12 at 17:57
  • @KerrekSB, thanks, I have run this program multiple times(also increasing the loop counter) but it seems to produce correct output every time. – quartz May 12 '12 at 18:02
  • 2
    Possible duplicate of http://stackoverflow.com/questions/467938/stdout-thread-safe-in-c-on-linux – Tudor May 12 '12 at 18:02
  • 1
    @quartz: Well, you were asking for guarantees, not empirical measurements. – Kerrek SB May 12 '12 at 18:03
  • 1
    @KerrekSB: That's very bad advice. A single `write` is **not** guaranteed to be atomic except in very specific situations, and `write` can always return with a short write, in which case you'll have to call `write` again to write out the remainder, and another thread can race between the two `write` calls. On the other hand, stdio **is** required to be atomic with respect to other accesses through the same `FILE` stream (but not with respect to other users of the same underlying file accessing it through different `FILE` streams). – R.. GitHub STOP HELPING ICE May 12 '12 at 19:46
  • @R..: What about the actual system call, though, not just the C wrapper function? Isn't that atomic? – Kerrek SB May 12 '12 at 20:16
  • @KerrekSB: No, not necessarily. And even if it were, that wouldn't help, because it's allowed to *return* after only writing 1 byte, in which case you'd have to call it again to write the rest, and the operation as a whole would not be atomic. – R.. GitHub STOP HELPING ICE May 12 '12 at 20:31
  • @R..: I see. OK, never mind then. – Kerrek SB May 12 '12 at 20:33
  • There is one case where atomicity is guaranteed: writing to pipes with sizes smaller than `PIPE_BUF`. In that case, either the whole write or no write at all will happen (and the latter is only possible with interrupting signals), and the write it atomic in the sense that no other write can come between any of the written bytes. – R.. GitHub STOP HELPING ICE May 12 '12 at 20:36
  • @Tudor, the answer there is a bit outdated since C11 now has a thread model. – Jens Gustedt May 12 '12 at 21:05
  • Does C11 have anything to say about atomicity of stdio, though? I didn't see anything. – R.. GitHub STOP HELPING ICE May 12 '12 at 21:21
  • @R.. but you did see my answer, no? "data races" is the terminology of the standard for non-atomicity. – Jens Gustedt May 14 '12 at 11:23

1 Answers1

3

You have incompatible assumptions in your question. OpenMp is not part of the C standard, so the C specification can't say anything about the thread model of OpenMp and ensure anything about safety of its proper functions. Until recently C didn't even have a thread model.

C11 now has its own thread model, and in that thread model the functions that operate on IO streams are thread safe:

Each stream has an associated lock that is used to prevent data races when multiple threads of execution access a stream, and to restrict the interleaving of stream operations performed by multiple threads. Only one thread may hold this lock at a time. The lock is reentrant: a single thread may hold the lock multiple times at a given time.

I don't think that there is yet a compiler out there that implements C11 fully, but typically the C library on POSIX systems would fulfill this particular requirement. When there will be such a complying implementation, it would be up to the OpenMp implementation that would sit on top of it to document if its thread model would be consistent with the one of C11.

Jens Gustedt
  • 76,821
  • 6
  • 102
  • 177
  • Not just "typically". POSIX requires all operations on stdio `FILE`s to behave atomically with respect to threads. If you want to group multiple separate stdio calls into an atomic operation, you can use the `flockfile` and `funlockfile` functions (POSIX). – R.. GitHub STOP HELPING ICE May 12 '12 at 19:41
  • @R.. sure. I meant the "typically" for one example of a family of systems where this requirement is fulfilled. I have no idea if other systems do this alike, nor if medieval implementations of POSIX (as OS X for example) already have this. I remember that when programming on IRIX (which supposedly was POSIX) there were a lot of problems with intermangled IO from different threads. – Jens Gustedt May 12 '12 at 21:04