0

So i have some code with a double checked locking solution for reading data files in multi threaded (with openmp) application, which looks something like:

logical, dimension(10,10) :: is_data_loaded
is_data_loaded=.false.

! Other code

subroutine load(i,j)
    integer,intent(in) :: i,j ! Indexes into array is_data_loaded
    if(is_data_loaded(i,j)) return
    !$OMP CRITICAL(load data)
        if(.not.is_data_loaded(i,j)) then
            call load_single_file(i,j)
            is_data_loaded(i,j) = .true.
        endif
    !$OMP END CRITICAL(load_data)
end subroutine 

Where I'm worried that if two threads get to the critical region at the same time (with the same i,j index) the second gets blocked by the first one entering the region but once the first finishes the second thread may start executing the critical block before seeing the updated is_data_loaded flag and thus we get into a problem with two threads updating the same data.

So firstly is this an issue with opemp critical blocks? I'm unsure of the semantics and whether the standard says something like "everything must be consistent across threads before the next thread runs in a critical block" or not. And if it is a problem, would just wrapping the read/writes to is_data_loaded in an omp atomic statement be sufficient?

Rob
  • 574
  • 1
  • 4
  • 17
  • There are locks in OpenMP. https://stackoverflow.com/questions/2396430/how-to-use-lock-in-openmp – Vladimir F Героям слава Mar 18 '19 at 18:29
  • Thanks that's good to now, but won't I still have a potential race condition between one thread finishing and the next starting (where the second may not have synchronised the change in is_data_loaded)? – Rob Mar 19 '19 at 08:24
  • Well, you didn't tell us what kind of race condition there is supposed to be. There is no race condition in your code even without any `critical` provided you always call the `load` for a different index. You really should prepare a [mcve] and show the race condition you want to avoid. The code should include calling of `load()` and what happens inside `load_single_file`. – Vladimir F Героям слава Mar 19 '19 at 09:22

1 Answers1

0

I think the code is wrong, as the threads might indeed not see the updates of is_data_loaded after another thread has set it from the critical region. While the critical region will ensure that the corresponding memory flushes occur, the thread executing the if(is_data_loaded(i,j)) return might not see the update, as this statement might still see outdated data.

I think adding !$omp flush before the if(is_data_loaded(i,j)) return is needed to ensure that all data has been flushed and is_data_loaded(i,j) is loaded with the most recent data.

Michael Klemm
  • 2,658
  • 1
  • 12
  • 15
  • I can understand that in a loop where one would get stuck with one value possibly in a register or in some weird non-cache-coherent NUMA, but here there is no loop in the subroutine. – Vladimir F Героям слава Mar 30 '19 at 21:07
  • Sorry, you're right there's no loop. But still the first `if` does not necessarily see the latest update to the array from another thread. OpenMP does not make such a guarantee in it's memory model. – Michael Klemm Apr 01 '19 at 06:47