Согласно спецификации OpenMP (v4.0), следующая программа содержит возможную гонку данных из-за несинхронизированного чтения/записи i
:
int i{0}; // std::atomic<int> i{0};
void write() {
// #pragma omp atomic write // seq_cst
i = 1;
}
int read() {
int j;
// #pragma omp atomic read // seq_cst
j = i;
return j;
}
int main() {
#pragma omp parallel
{ /* code that calls both write() and read() */ }
}
Возможные решения, которые пришли мне в голову, показаны в коде в виде комментариев:
- для защиты записи и чтения
i
с#pragma omp atomic write/read
, - для защиты записи и чтения
i
с#pragma omp atomic write/read seq_cst
, - использовать
std::atomic<int>
вместоint
в качестве типаi
.
Вот сгенерированные компилятором инструкции для x86_64 (с -O2
во всех случаях):
GNU g++ 4.9.2: i = 1; j = i;
original code: MOV MOV
#pragma omp atomic: MOV MOV
// #pragma omp atomic seq_cst: MOV MOV
#pragma omp atomic seq_cst: MOV+MFENCE MOV (see UPDATE)
std::atomic<int>: MOV+MFENCE MOV
clang++ 3.5.0: i = 1; j = i;
original code: MOV MOV
#pragma omp atomic: MOV MOV
#pragma omp atomic seq_cst: MOV MOV
std::atomic<int>: XCHG MOV
Intel icpc 16.0.1: i = 1; j = i;
original code: MOV MOV
#pragma omp atomic: * *
#pragma omp atomic seq_cst: * *
std::atomic<int>: XCHG MOV
* Multiple instructions with calls to __kmpc_atomic_xxx functions.
Мне интересно, почему компилятор GNU/clang не генерирует никаких специальных инструкций для #pragma omp atomic
записи. Я ожидаю таких же инструкций, как и для std::atomic
, то есть либо MOV+MFENCE
, либо XCHG
. Любое объяснение?
ОБНОВЛЕНИЕ
g++ 5.3.0 выдает MFENCE
вместо #pragma omp atomic write seq_cst
. Это правильное поведение, я считаю. Без seq_cst
получается простое MOV
, чего достаточно для атомарности, отличной от SC.
В моем Makefile была ошибка, g++ 4.9.2 также выдает MFENCE
для атомарной записи CS. Извините, ребята, за это.
Clang 3.5.0 не реализует атомарность OpenMP SC, спасибо Христо Илиеву за указание на это.
mfence
сразу послеmovl $1, i(%rip)
для последовательно согласованной атомарной записи. - person Hristo Iliev   schedule 17.02.2016mfence
для атомарной записи OpenMP SC? То есть сi
типаint
? Мой GCC только дляstd::atomic<int>
. - person Daniel Langr   schedule 18.02.2016mfence
для атомарной записи SC OpenMP. Итак, проблема была с (моим) g++ 4.9.2. - person Daniel Langr   schedule 19.02.2016