Concurrency 在浮点加法上使用OpenMP Reduce是否有变通方法? 我目前正在使用C++和OpenMP并行化嵌套for循环。在不深入该计划的实际细节的情况下,我构建了一个关于我使用的以下概念的基本示例: float var = 0.f; float distance = some float array; float temp[] = some float array; for(int i=0; i < distance.size; i++){ \\some work for(int j=0; j < temp.size; j++){ var += temp[i]/distance[j] } } float var=0.f; 浮动距离=一些浮动数组; 浮点温度[]=某些浮点数组; 对于(int i=0;i区域时,您还需要它的初始值,那么您也必须考虑添加第一私有< /代码>(如果您已经去了还原< /代码>,如已经注意到的),则不需要()

Concurrency 在浮点加法上使用OpenMP Reduce是否有变通方法? 我目前正在使用C++和OpenMP并行化嵌套for循环。在不深入该计划的实际细节的情况下,我构建了一个关于我使用的以下概念的基本示例: float var = 0.f; float distance = some float array; float temp[] = some float array; for(int i=0; i < distance.size; i++){ \\some work for(int j=0; j < temp.size; j++){ var += temp[i]/distance[j] } } float var=0.f; 浮动距离=一些浮动数组; 浮点温度[]=某些浮点数组; 对于(int i=0;i区域时,您还需要它的初始值,那么您也必须考虑添加第一私有< /代码>(如果您已经去了还原< /代码>,如已经注意到的),则不需要(),concurrency,openmp,Concurrency,Openmp,我尝试以以下方式并行化上述代码: float var = 0.f; float distance = some float array; float temp[] = some float array; #pragma omp parallel for default(shared) for(int i=0; i < distance.size; i++){ \\some work #pragma omp parallel for reduction(+:var)

我尝试以以下方式并行化上述代码:

float var = 0.f;
float distance = some float array;
float temp[] = some float array;
#pragma omp parallel for default(shared)
for(int i=0; i < distance.size; i++){
    \\some work
    #pragma omp parallel for reduction(+:var)
    for(int j=0; j < temp.size; j++){
        var += temp[i]/distance[j]
    }
}
float var=0.f;
浮动距离=一些浮动数组;
浮点温度[]=某些浮点数组;
#默认值为pragma omp parallel(共享)
对于(int i=0;i

然后我将串行程序输出与并行程序输出进行比较,结果不正确。我知道这主要是因为浮点运算不是关联的。但是有什么解决方法可以给出准确的结果吗?

虽然在某些情况下,浮点运算缺乏关联性可能是一个问题,但您在这里展示的代码暴露了一个更重要的问题,您需要首先解决:外部循环中的
var
变量的状态

事实上,由于
var
i
循环中被修改,即使只在
i
循环的
j
部分,它也需要以某种方式被“私有化”。现在,它需要获得的确切状态取决于您希望它在退出封闭的
parallel
区域时存储的值:

  • 如果您根本不关心它的值,只需声明它
    private
    (或者更好,在
    并行
    区域内声明它)
  • 如果在
    i
    循环的末尾需要它的最终值,并且考虑到它累加了一个值的总和,那么很可能需要声明它
    reduce(+:)
    ,尽管
    lastprivate
    也可能是您想要的(没有进一步的详细信息,不可能说)
  • 如果代码>私有< /代码>或<代码> ListPosib<代码>是您所需要的,但在“代码>并行< /代码>区域时,您还需要它的初始值,那么您也必须考虑添加<代码>第一私有< /代码>(如果您已经去了<代码>还原< /代码>,如已经注意到的),则不需要(
这应该足以解决您的问题

现在,在您的代码片段中,您还并行化了内部循环。使用嵌套并行通常不是一个好主意。因此,除非您有非常令人信服的理由这样做,否则只并行化外部循环,而不使用内部循环,您可能会获得更好的性能。这并不意味着内部循环不会受益于p并行化,而是内部循环的几个实例将并行计算(每个实例都是顺序的,但整个过程是并行的)。
移除内部循环的并行化(除了使代码更快)的一个很好的副作用是,现在privates
var
变量中的所有累加都是按照与非并行时相同的顺序进行的。因此,您的(假设)外部循环中的浮点运算问题现在已经消失,只有在退出
并行
区域时需要进行最终缩减时,您才可能仍然在那里面对它们。

虽然在某些情况下,浮点运算缺乏关联性可能是一个问题,但此处显示的代码暴露了一个更大的问题e您需要首先解决的基本问题:外部循环中
var
变量的状态

事实上,由于
var
i
循环中被修改,即使只在
i
循环的
j
部分,它也需要以某种方式“私有化”。现在它需要获得的确切状态取决于您希望它在退出封闭的
parallel
区域时存储的值:

  • 如果您根本不关心它的值,只需声明它
    private
    (或者更好,在
    并行
    区域内声明它)
  • 如果在
    i
    循环的末尾需要它的最终值,并且考虑到它累加了一个值的总和,那么很可能需要声明它
    reduce(+:)
    ,尽管
    lastprivate
    也可能是您想要的(没有进一步的详细信息,不可能说)
  • 如果代码>私有< /代码>或<代码> ListPosib<代码>是您所需要的,但在“代码>并行< /代码>区域时,您还需要它的初始值,那么您也必须考虑添加<代码>第一私有< /代码>(如果您已经去了<代码>还原< /代码>,如已经注意到的),则不需要(
这应该足以解决您的问题

现在,在您的代码片段中,您还并行化了内部循环。使用嵌套并行通常不是一个好主意。因此,除非您有非常令人信服的理由这样做,否则只并行化外部循环,而不使用内部循环,您可能会获得更好的性能。这并不意味着内部循环不会受益于p并行化,而是内部循环的几个实例将并行计算(每个实例都是顺序的,但整个过程是并行的)。 移除内部循环的并行化(除了使代码更快)的一个很好的副作用是,现在privates
var
变量中的所有累加都是按照与非并行时相同的顺序进行的。因此,您的(假设)外部循环中的浮点运算问题现在已经消失,只有在退出
并行
区域时需要进行最终缩减时,您才可能仍然面临这些问题