我在open 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我做错了什么?
在我看来,一切看起来都很好。
发布于 2011-03-20 20:47:14
首先,一个简单的1000个元素的点积没有足够的计算成本来证明多线程是合理的-您将在通信和同步成本上付出比您在性能上获得的更多的成本,这是不值得的。
其次,它看起来像是在每个线程中计算完整的点积,而不是在多个线程之间划分计算并在最后组合结果。
下面是一个如何在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非常适合进行粗粒度并行。通常,在进行并行编程时,在重新同步之前可以进行的计算“块”越大越好。特别是随着内核数量的增加,通信和同步成本也会增加。假装每次同步(抓取新的索引或索引块来执行,进入临界区,等等)花费你10毫秒,或100万条指令,以便更好地了解何时/何处/如何并行你的代码。
发布于 2011-03-20 21:10:22
这个问题和你最近提出的问题是一样的。您在一个变量中累加值,您必须告诉OpenMp如何做到这一点:
#pragma omp for reduction(+: dpp)
for(size_t i=0; i<SIZE; i++){
dpp += u[i]*v[i];
}使用循环局部变量作为索引,这就是你所需要的,忘掉你围绕它所做的所有事情。如果你想知道编译器对你的代码做了什么,用-S运行它,并检查汇编器的输出。这可能非常有指导意义,因为这样您就可以了解这样的简单语句在被并行化时会达到什么程度。
并且不要使用int作为循环索引。大小和类似的东西都是size_t。
https://stackoverflow.com/questions/5368038
复制相似问题