C++ OpenMP返回错误的结果
下面的代码应该使用4个线程来计算0到1000之间所有数字的总和。它应该返回499500,但每次执行时返回的值不同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_
#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
的值。要解决此问题,您可以使用OpenMPreduce
子句,该子句从一个可以读取:
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