Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ OpenMP返回错误的结果_C++_Multithreading_Performance_Parallel Processing_Openmp - Fatal编程技术网

C++ OpenMP返回错误的结果

C++ OpenMP返回错误的结果,c++,multithreading,performance,parallel-processing,openmp,C++,Multithreading,Performance,Parallel Processing,Openmp,下面的代码应该使用4个线程来计算0到1000之间所有数字的总和。它应该返回499500,但每次执行时返回的值不同 #include <omp.h> #include <iostream> using namespace std; int main (int argc, char *argv[]) { int nthreads, i, tid; float total; #pragma omp parallel num_

下面的代码应该使用4个线程来计算0到1000之间所有数字的总和。它应该返回499500,但每次执行时返回的值不同

#include <omp.h>
#include <iostream>

using namespace std;

int main (int argc, char *argv[])
{
        int nthreads, i, tid;
        float total;

        #pragma omp parallel num_threads(4) 
        {
            tid = omp_get_thread_num();
            if (tid == 0) {
                nthreads = omp_get_num_threads();
                cout << "Número de threads = " << nthreads <<endl;
            }
           #pragma omp barrier

           total = 0.0;
           #pragma omp for schedule(dynamic,10) private(i)
           for (i=0; i<1000; i++)
               total = total + i*1.0;
        } 
        cout << "Total = " <<total << endl;
        return 0;
}
#包括
#包括
使用名称空间std;
int main(int argc,char*argv[])
{
int nthreads,i,tid;
浮动总额;
#pragma omp并行num_线程(4)
{
tid=omp_get_thread_num();
如果(tid==0){
nthreads=omp_get_num_threads();

cout代码中发生的情况是,您有多个线程同时修改变量
total
的值。要解决此问题,您可以使用OpenMP
reduce
子句,该子句从一个可以读取:

reduce子句可用于执行某些形式的重复 并行计算(…)。用于并行计算和工作共享 构造时,将创建每个列表项的私有副本,每个列表项对应一个副本 隐式任务,就好像使用了private子句。(…) 然后按照上面的指定初始化私有副本 为其指定缩减子句的区域,原始列表 项目通过将其原始值与最终值相结合进行更新 使用指定的 还原标识符

关于减损条款如何工作的更详细的解释,请看下面的例子

因此,要解决代码中的竞争条件,只需将其更改为:

        #pragma omp for schedule(dynamic,10) private(i) reduction(+:total)
        for (i=0; i<1000; i++)
             total = total + i*1.0;
只需将其设置在平行区域之前

关于变量tid本身还有另一个争用条件,它在线程之间共享,并在并行区域内同时更新:

total = 0.0;
tid = omp_get_thread_num();
这可以通过将
tid
设置为每个线程的私有来解决,例如:

int tid = omp_get_thread_num();
旁注

在OpenMP中,由
#pragma omp for
包围的最外层循环的索引变量(
i
)已经是私有的,因此
private(i)
子句实际上是不必要的

另一点是
时间表(动态,10)
;除非您只是在玩,否则它实际上更有意义(性能方面)使用调度
静态
,因为该代码不会导致负载平衡问题。
动态
调度有额外的开销,在运行时将任务分配给线程,而
静态
调度中的分配是在编译时执行的

最后,以下是:

    tid = omp_get_thread_num();
    if (tid == 0) {
        nthreads = omp_get_num_threads();
        cout << "Número de threads = " << nthreads <<endl;
    }
    #pragma omp master
    {
        nthreads = omp_get_num_threads();
        cout << "Número de threads = " << nthreads <<endl;
    }
#include <omp.h>
#include <iostream>

using namespace std;

int main (int argc, char *argv[])
{
        float total = 0.0;

        #pragma omp parallel num_threads(4) 
        {
           #pragma omp master
           {
                int nthreads = omp_get_num_threads();
                cout << "Número de threads = " << nthreads <<endl;
           }
           #pragma omp barrier

           #pragma omp for reduction(+:total)
           for (int i=0; i < 1000; i++)
               total = total + i*1.0;
        } 
        cout << "Total = " <<total << endl;
        return 0;
}
Número de threads = 4
Total = 499500