Атомный минимум на x86 с использованием OpenMP

Поддерживает ли OpenMP атомарный минимум для C ++ 11? Если в OpenMP нет переносимого метода: есть ли способ сделать это с помощью функции x86 или amd64?

В спецификациях OpenMP я ничего не нашел для C ++, но версия Fortran, кажется, поддерживает это. См. 2.8.5 v3.1 для деталей. Для C ++ говорится

binop является одним из +, *, -, /, &, ^, |, <<или >>.

но для Фортрана говорится

intrinsic_procedure_name является одним из MAX, MIN, IAND, IOR или IEOR.

В случае, если вас интересует больше контекста: я ищу свободный от мьютекса способ сделать следующее:

vector<omp_lock_t>lock;
vector<int>val;

#pragma omp parallel
{
// ...
int x = ...;
int y = ...;
if(y < val[x]){
omp_set_lock(&lock[x]);
if(y < val[x])
val[x] = y;
omp_unset_lock(&lock[x]);
}
}

Я знаю, что вы можете вычислить минимум, используя алгоритм уменьшения. Я знаю, что существуют обстоятельства, когда это в значительной степени превосходит любой атомный минимальный подход. Однако я также знаю, что это не так в моей ситуации.

РЕДАКТИРОВАТЬ: один вариант, который немного быстрее в моем случае это

  int x = ...;
int y = ...;
while(y < val[x])
val[x] = y;

но это не атомная операция.

Все новые графические процессоры имеют эту функцию, и мне не хватает ее на процессоре. (См. Atom_min для OpenCL.)

7

Решение

Спецификация OpenMP для C ++ не имеет поддержки атомарного минимума. Как и C ++ 11.

Я предполагаю, что в вашем алгоритме x может вычислить любой допустимый индекс, независимо от потока.
Я бы предложил изменить ваш алгоритм, чтобы каждый поток использовал свой val массив и затем сделать окончательное согласование в конце, который также может быть распараллелен по индексу. Это позволит полностью избежать блокировок и разрозненности и даст вам преимущество разделения данных для каждого потока, то есть нет шансов на ложное совместное использование кэша. Другими словами, это должно быть быстрее.

4

Другие решения

Других решений пока нет …