【问题标题】:Couldn't get acceleration OpenMP无法获得加速 OpenMP
【发布时间】:2012-06-20 08:54:38
【问题描述】:

我正在使用 OpenMP 用 C++ 编写简单的并行程序。 我正在使用 Windows 7 和 Microsoft Visual Studio 2010 Ultimate。 我将项目的 Language 属性更改为“Yes/OpenMP”以支持 OpenMP

这里我提供代码:

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

using namespace std;

double sum; 
int i;
int n = 800000000;

int main(int argc, char *argv[])
{               
    omp_set_dynamic(0);
    omp_set_num_threads(4); 

    sum = 0;    
    #pragma omp for reduction(+:sum)
    for (i = 0; i < n; i++)
        sum+= i/(n/10);

    cout<<"sum="<<sum<<endl;        

    return  EXIT_SUCCESS;
}

但是,我无法通过更改x 中的omp_set_num_threads(x); 来获得任何加速 用不用OpenMp没关系,计算时间都是一样的,7秒左右。

有人知道问题出在哪里吗?

【问题讨论】:

  • 尽管如此,我很确定这个计算有一个封闭的公式。事实上,你可能错过了一个演员表,因为正如目前所写的那样,所有is
  • 如果你想要速度,那么规则 No1 是避免不必要的计算,例如在你的内部循环中将 sum += i/(n/10) 替换为 sum += i*d; 并在之前声明 const double d=10.0/n;。无论如何,一个聪明的编译器可能会对此进行优化,但最好不要依赖它(例如,编译器可能会优化为除以常数,这会显着降低效率)。
  • 我建议你忘记omp_set_num_threads(),而是设置环境变量OMP_NUM_THREADS。否则,您可能会将程序的线程数固定为比实际运行它的机器的 CPU 计数高得多的值。

标签: c++ multithreading performance openmp


【解决方案1】:

您的pragma 语句缺少parallel 说明符:

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

using namespace std;

double sum; 
int i;
int n = 800000000;

int main(int argc, char *argv[])
{               
    omp_set_dynamic(0);
    omp_set_num_threads(4); 

    sum = 0;    
    #pragma omp parallel for reduction(+:sum)  //  add "parallel"
    for (i = 0; i < n; i++)
        sum+= i/(n/10);

    cout<<"sum="<<sum<<endl;        

    return  EXIT_SUCCESS;
}

顺序:

sum=3.6e+009
2.30071

平行:

sum=3.6e+009
0.618365

这是一个使用超线程加速的版本。我不得不将迭代次数增加 10 倍,并将数据类型提升到 long long

double sum; 
long long i;
long long n = 8000000000;

int main(int argc, char *argv[])
{               
    omp_set_dynamic(0);
    omp_set_num_threads(8); 

    double start = omp_get_wtime();


    sum = 0;    
    #pragma omp parallel for reduction(+:sum)
    for (i = 0; i < n; i++)
        sum+= i/(n/10);

    cout<<"sum="<<sum<<endl;       

    double end = omp_get_wtime(); 
    cout << end - start << endl;
    system("pause");

    return  EXIT_SUCCESS;
}

线程数:1

sum=3.6e+014
13.0541

线程数:2

sum=3.6e+010
6.62345

线程数:4

sum=3.6e+010
3.85687

线程数:8

sum=3.6e+010
3.285

【讨论】:

  • 非常小众!我及时得到了加速!)
  • @NurlanKenzhebekov 我已经用一个版本更新了我的答案,该版本在我自己的四核 Core i7 机器上显示了一些超线程加速。它仍然不是 4 倍,但 8 线程显示出比 4 线程有所改进。
【解决方案2】:

除了 Mystical 指出的错误之外,您似乎认为 openMP 可以变魔术。它最多可以使用您机器上的所有内核。如果你有 2 个内核,如果你在 np>=2 的情况下调用 omp_set_num_threads(np) 可能会减少 2 个执行时间,但是对于比内核数量大得多的 np,由于并行化开销,代码效率会很低。

Mystical 中的示例显然在 np=4 的至少 4 个内核上运行。

【讨论】:

  • 我的机器有 4 个物理内核,它支持 8 个线程,因为在任务管理器中我看到 8 列 CPU 负载。但即使我设置 np=8,我也无法获得超过 3.9 的加速度...你能解释为什么即使我有 8 列 CPU 负载我也无法获得超过 4 的加速度吗?
  • @NurlanKenzhebekov 那是因为超线程在这个特定示例中没有用。从我之前看到的情况来看,主要运行整数除法的代码并没有从超线程中受益(如果有的话)。
  • @Nurlan 是的,您的代码受到计算而非数据加载和存储的限制,因此线程多于内核无济于事。如果你的代码是数据受限的,那么每个线程大部分时间都做很少的计算,超线程将是有益的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-06-17
  • 2016-09-14
  • 2016-09-14
  • 1970-01-01
  • 1970-01-01
  • 2014-12-13
相关资源
最近更新 更多