我有一个在并行 for 循环中调用的函数。除了需要锁定的一个变量增量之外,该函数中的所有内容都可以并行完成。我尝试将
#pragma omp atomic
放在指令之前,但似乎由于该函数仅在并行循环中调用,而不是自行并行化,因此编译器会调用错误:error: ‘#pragma’ is not allowed here
。
我的代码看起来像这样(c++):
class MyClass {
private:
int **data;
int data_size;
public:
size_t myFunc(int r, int i) {
int n = longFunc(...); // Long code that can be done in parallel if needed
for (int j = 0; j < data_size; j++) {
#pragma omp atomic // error: ‘#pragma’ is not allowed here
data[r][j] += n + data[i][i] + i; // This part cannot be parallelised
}
return n;
}
/* ... */
};
int main() {
MyClass s;
int row_to_change = 0;
#pragma omp parallel for
for (int i = 0; i < s.size(); i++) {
size_t n = s.myFunc(row_to_change, i); // Parallel calls to the function
/* ... */
}
return 0;
}
知道如何保持
myFunc
的主要部分可能并行化,但在成员 data
的修改上锁定线程吗?
可能没有回答您真正的问题,而是纠正一个误解。 您声明“由于该函数仅在并行循环中调用,并且本身并未并行化,因此编译器会调用错误:错误:此处不允许‘#pragma’。”
然而,这是错误的。如果您在启用 OpenMP 的情况下进行编译,则可以在任何地方使用 OpenMP 原子操作,编译器不必看到代码完全处于任何并行性中。
考虑这样的代码:-
void lockedIncr(int *p)
{
#pragma omp atomic
(*p)++;
}
由于我们完全自行编译它,编译器显然无法知道它将被调用的上下文。
如果您在编译器资源管理器上查看here,您可以看到它已成功编译,并生成了人们期望的代码:-
lockedInc(int*):
lock add DWORD PTR [rdi], 1
ret