正确使用interal函数和openmp

dan*_*345 5 c++ loops openmp

我有一个调用内部函数的for循环:

some variables
for(int i=0; i< 10000000; i++)
    func(variables)
Run Code Online (Sandbox Code Playgroud)

基本上,func获取对某个数组A的引用,并在A [i]中插入值 - 所以我确信每次调用func实际上都会尝试将值插入A中的不同位置,而所有其他输入变量都保持不变与for循环之前相同.所以func是线程安全的.

我可以安全地将代码更改为

some variables
#pragma omp parallel for
for(int i=0; i< 10000000; i++)
    func(variables)
Run Code Online (Sandbox Code Playgroud)

根据我对openmp教程的理解,这还不够好 - 因为openmp库不会知道给func的变量是真的线程安全的,所以这会产生尝试执行同步,这会减慢速度,我需要声明变量私有等.但实际上,当尝试上面的代码时,它似乎确实更快和并行工作 - 这是否符合预期?我只是想确保我没有错过任何东西.

func的声明:

 func(int i, int client_num, const vector<int>& vec)
Run Code Online (Sandbox Code Playgroud)

min*_*ang 4

首先,OpenMP 无法神奇地确定对代码的依赖关系。您有责任确保代码对于并行化来说是正确的。

为了安全地并行化 for 循环,func不得具有循环携带的流依赖性或迭代间依赖性,特别是对于先写后读模式。另外,您必须检查没有静态变量。(实际上,在这个简短的答案中写下安全并行化的条件要复杂得多。)


您的描述funcfunc会将变量写入不同的位置。如果是这样,您可以通过 put 安全地并行化pragma omp parallel for,除非其他计算不存在禁止并行化的依赖关系。

您的原型funcfunc(int i, int client_num, const vector<int>& vec)

有一个vector,但它是一个常量,所以vec不应该有任何依赖性。从不同线程同时读取是安全的。

但是,你说输出是不同的。这意味着出了什么问题。不可能说出问题是什么。显示函数的原型毫无帮助;我们需要知道进行了什么样的计算func

尽管如此,诊断的一些步骤是:

  • 检查代码中的依赖关系。您不得具有如下所示的依赖关系。请注意,数组A具有循环进位依赖性,这将阻止并行化:

for (int k = 1; k <N; ++k) A[k] = A[k-1]+1;

  • 检查func是可重入的还是线程安全的。大多数情况下,静态和全局变量可能会杀死您的代码。如果是这样,可以通过私有化来解决这个问题。在 OpenMP 中,您可以在子句中声明这些变量private。此外,OpenMP 中还有threadprivatepragma。