为什么我的C代码使用OpenMP更慢
我尝试使用OpenMP在CPU上执行多线程编程。 我有很多for循环是很好的候选人并行。 我在这里附上我的代码的一部分。 当我使用第一个#pragma omp parallel进行缩减时,我的代码更快,但是当我尝试使用相同的命令来并行化其他循环时,它会变得更慢。 有没有人有任何想法,为什么它是这样的?
.
.
.
omp_set_dynamic(0);
omp_set_num_threads(4);
float *h1=new float[nvi];
float *h2=new float[npi];
while(tol>0.001)
{
std::fill_n(h2, npi, 0);
int k,i;
float h222=0;
#pragma omp parallel for private(i,k) reduction (+: h222)
for (i=0;i<npi;++i)
{
int p1=ppi[i];
int m = frombus[p1];
for (k=0;k<N;++k)
{
h222 += v[m-1]*v[k]*(G[m-1][k]*cos(del[m-1]-del[k])
+ B[m-1][k]*sin(del[m-1]-del[k]));
}
h2[i]=h222;
}
//*********** h3*****************
std::fill_n(h3, nqi, 0);
float h333=0;
#pragma omp parallel for private(i,k) reduction (+: h333)
for (int i=0;i<nqi;++i)
{
int q1=qi[i];
int m = frombus[q1];
for (int k=0;k<N;++k)
{
h333 += v[m-1]*v[k]*(G[m-1][k]*sin(del[m-1]-del[k])
- B[m-1][k]*cos(del[m-1]-del[k]));
}
h3[i]=h333;
}
.
.
.
}
我不认为你的OpenMP代码和没有OpenMP的结果相同。 我们只关注代码中的h2[i]
部分(因为h3[i]
具有相同的逻辑)。 h2[i]
对索引i
有依赖性(即h2 [1] = h2 [1] + h2 [0])。 你所做的OpenMP减少不会给出正确的结果。 如果你想用OpenMP来减少你需要的内部循环,像这样:
float h222 = 0;
for (int i=0; i<npi; ++i) {
int p1=ppi[i];
int m = frombus[p1];
#pragma omp parallel for reduction(+:h222)
for (int k=0;k<N; ++k) {
h222 += v[m-1]*v[k]*(G[m-1][k]*cos(del[m-1]-del[k])
+ B[m-1][k]*sin(del[m-1]-del[k]));
}
h2[i] = h222;
}
但是,我不知道这是否会非常有效。 另一种方法是在外部循环中并行填充h2[i]
而不减少,然后在串行中处理依赖关系。 即使串行循环没有并行化,它仍然应该对计算时间有小的影响,因为它没有超过k
的内部循环。 这应该给与有和没有OpenMP同样的结果,并且仍然很快。
#pragma omp parallel for
for (int i=0; i<npi; ++i) {
int p1=ppi[i];
int m = frombus[p1];
float h222 = 0;
for (int k=0;k<N; ++k) {
h222 += v[m-1]*v[k]*(G[m-1][k]*cos(del[m-1]-del[k])
+ B[m-1][k]*sin(del[m-1]-del[k]));
}
h2[i] = h222;
}
//take care of the dependency serially
for(int i=1; i<npi; i++) {
h2[i] += h2[i-1];
}
请记住,创建和销毁线程是一个耗时的过程; 记下该过程的执行时间并亲自查看。 您只使用两次并行缩减,这可能比串行缩减更快,但创建线程的初始成本可能仍然较高。 尝试平行化最外层循环(如果可能),看看你是否可以获得加速。
链接地址: http://www.djcxy.com/p/79231.html