简单的 OpenMP 并行 for 循环比串行计算慢

simple OpenMP parallel for loop slower than serial computation

我是并行化的新手,希望我没有在浪费任何人的时间。我已经问过一些已经使用过 openMP 的朋友,但他们帮不了我。所以我猜想我的案例对其他人来说也可能很有趣,至少出于教育目的,我试图尽可能好地记录它。这是两个示例,其中一个 100% 取自 Tim Mattson 在 youtube 上的教程,另一个以某种方式进行了简化,但我想仍然是一种标准方法。在这两种情况下,计算时间都与少数迭代的线程数成比例,但对于非常大量的迭代,计算时间似乎收敛到相同的数字。这当然是错误的,因为我希望计算时间在几次迭代中是相似的,并且真正针对大量迭代进行了优化。

这里是两个例子,都是用

编译的

g++ -fopenmp main.cpp -o out

线程模型:posix gcc 版本 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04),在 Ubuntu 14.04 以及以下 header:

#include <omp.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <chrono>
#include <iostream>

using namespace std;


#define NUMBER_OF_THREADS 2
static long num_steps = 1000000000;

现在,我现在正在使用的计算机上的内核数量是 8(intel i7),因此我希望 2 到 4 之间的任何线程数在计算方面带来一些很大的优势时间.

示例 1:

int main() { 

omp_set_num_threads(NUMBER_OF_THREADS);
double step = 1.0/(double) num_steps, pi=0.0;

auto begin = chrono::high_resolution_clock::now();

#pragma omp parallel 
{ 
    int i, ID, nthrds;
    double x, sum = 0; 

    ID = omp_get_thread_num();
    nthrds = omp_get_num_threads();

    for (i=ID; i<num_steps; i=i+nthrds) { 
        x = (i+0.5)*step; 
        sum = sum + 4.0/(1.0+x*x); 
    } 

    #pragma omp critical
    pi += step*sum; 
} 

auto end = chrono::high_resolution_clock::now();
cout << chrono::duration_cast<chrono::nanoseconds>(end-begin).count()/1e6 << "ms\n";

return 0; 

}

示例 2:

int main() { 

    omp_set_num_threads(NUMBER_OF_THREADS);
    double pi=0, sum = 0; 
    const double step = 1.0/(double) num_steps;

    auto begin = chrono::high_resolution_clock::now();

    // #pragma omp parallel 
    { 
        #pragma omp parallel for reduction(+:sum)
        for (int i=0; i<num_steps; i++) { 
            double x = (i+0.5)*step; 
            sum += 4.0/(1.0+x*x); 
        } 
    } 

    pi += step*sum; 

    auto end = std::chrono::high_resolution_clock::now();
    cout << chrono::duration_cast<chrono::nanoseconds>(end-begin).count()/1e6 << "ms\n";

    return 0; 

}

现在,一开始我认为示例 2 因变量的减少而变慢,这扰乱了并行化,但在示例 1 中几乎没有任何共享。如果我正在做一些非常愚蠢的事情,或者我是否可以详细说明问题的更多方面,请告诉我。感谢大家。

正如吉尔斯在评论中 post 所说,问题是我用 clock() 测量时间,它把核心的所有动作加起来。 与

chrono::high_resolution_clock::now();

我得到了预期的加速。

对我来说,这个问题已经解决了,但也许我们可以把这个作为一个例子,供未来像我这样的菜鸟参考。如果有人 mod 不这么认为,那么 post 可以被淘汰。 再次感谢您的帮助