我正在开放MP中实现并行点产品
我有这段代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <math.h>
#include <omp.h>
#define SIZE 1000
int main (int argc, char *argv[]) {
float u[SIZE], v[SIZE], dp,dpp;
int i, j, tid;
dp=0.0;
for(i=0;i<SIZE;i++){
u[i]=1.0*(i+1);
v[i]=1.0*(i+2);
}
printf("\n values of u and v:\n");
for (i=0;i<SIZE;i++){
printf(" u[%d]= %.1f\t v[%d]= %.1f\n",i,u[i],i,v[i]);
}
#pragma omp parallel shared(u,v,dp,dpp) private (tid,i)
{
tid=omp_get_thread_num();
#pragma omp for private (i)
for(i=0;i<SIZE;i++){
dpp+=u[i]*v[i];
printf("thread: %d\n", tid);
}
#pragma omp critical
{
dp=dpp;
printf("thread %d\n",tid);
}
}
printf("\n dot product is %f\n",dp);
}
我是以pgcc -B -Mconcur -Minfo -o prog prog.c
我进入控制台的结果是:
33, Loop not parallelized: innermost
39, Loop not vectorized/parallelized: contains call
48, Loop not vectorized/parallelized: contains call
我做错了什么?
从我的角度来看,一切看起来都很好。
答案 0 :(得分:2)
首先,一个简单的1,000元素点产品没有足够的计算成本来证明多线程的合理性 - 你将在通信和同步成本上付出的代价比你在性能上所获得的要多得多,这是不值得的它
其次,看起来你正在计算每个线程中的完整点产品,而不是将计算分成多个线程并在最后组合结果。
以下是如何从https://computing.llnl.gov/tutorials/openMP/#SHARED
执行矢量点积的示例#include <omp.h>
main ()
{
int i, n, chunk;
float a[100], b[100], result;
/* Some initializations */
n = 100;
chunk = 10;
result = 0.0;
for (i=0; i < n; i++) {
a[i] = i * 1.0;
b[i] = i * 2.0;
}
#pragma omp parallel for \
default(shared) private(i) \
schedule(static,chunk) \
reduction(+:result)
for (i=0; i < n; i++)
result += (a[i] * b[i]);
printf("Final result= %f\n",result);
}
基本上,当你有大而昂贵的循环时,OpenMP很适合做粗粒度并行。通常,当您进行并行编程时,在重新同步之前可以执行的计算“块”越大越好。特别是随着核心数量的增加,通信和同步成本将增加。假设每次同步(抓取新索引或要执行的索引块,进入关键部分等)都需要花费10ms或1M指令来更好地了解何时/何地/如何并行化代码。
答案 1 :(得分:2)
问题仍然与您最新的问题相同。您正在变量中累积值,您必须告诉OpenMp如何执行此操作:
#pragma omp for reduction(+: dpp)
for(size_t i=0; i<SIZE; i++){
dpp += u[i]*v[i];
}
为索引使用循环局部变量,这就是你所需要的,忘掉你正在做的所有事情。如果你想看看编译器对你的代码做了什么,用-S运行它并检查汇编器输出。这可能非常有启发性,因为您可以了解这些简单的语句在何时进行并行化。
不要将int
用于循环索引。尺寸和类似的东西是size_t
。