Поддерживает ли 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.)
Спецификация OpenMP для C ++ не имеет поддержки атомарного минимума. Как и C ++ 11.
Я предполагаю, что в вашем алгоритме x
может вычислить любой допустимый индекс, независимо от потока.
Я бы предложил изменить ваш алгоритм, чтобы каждый поток использовал свой val
массив и затем сделать окончательное согласование в конце, который также может быть распараллелен по индексу. Это позволит полностью избежать блокировок и разрозненности и даст вам преимущество разделения данных для каждого потока, то есть нет шансов на ложное совместное использование кэша. Другими словами, это должно быть быстрее.
Других решений пока нет …