为什么这个简单的C ++ OpenMP程序使用多个线程会变慢?

时间:2018-03-16 23:58:00

标签: c++ performance openmp

为了学习OpenMP,我正在使用OpenMP运行一个简单的C ++程序来计算pi的值,基于以下视频:https://www.youtube.com/watch?v=OuzYICZUthM

不幸的是,我的程序似乎运行速度更快,线程更少,我不知道为什么。我的笔记本电脑有4个内核,因此它应该至少在一个以上的线程上运行得更快。

以下是代码:

http://localhost:3000/character-info

有人可以告诉我多线程为什么花费的时间超过单个线程?看一下这个问题上的类似帖子,看起来人们的代码存在问题导致它们在多个线程下运行速度变慢。但是,这段代码基于视频中的dude,但我在运行此代码时不应该遇到这个问题。

注意:程序使用数值积分来计算pi的值。积分的函数为4.0 /(1 + x * x),从0到1,精确计算为pi。

2 个答案:

答案 0 :(得分:3)

首先,我注意到我无法复制您的结果。对我来说,你的代码运行大约500毫秒,NUM_THREADS设置为1,大约130-140毫秒,NUM_THREADS设置为4,所以它按照我们对4核机器的预期进行缩放。

但是,这并不是我编写代码的方式。我开始简化代码(非常多)。 OpenMP的主要用例是当前没有与线程明确相关的任何内容,然后插入指令,并使其运行速度更快的代码。

我编写代码以更多地依赖OpenMP来处理减少等等,最后得到这样的结果:

#include <iostream>
#include <omp.h>
using namespace std;
static long num_steps = 100000000;
double step;

int main() {
    double pi = 0.0;
    step = 1.0 / (double)num_steps;

    double start_time = omp_get_wtime();

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

    pi *= step;

    double time = omp_get_wtime() - start_time;

    cout << pi << endl;
    cout << time * 1000 << endl;
}

至少对我而言,这与您的代码的速度大致相同 - 大约500毫秒而不启用OpenMP,大约130-140毫秒启用OpenMP。

答案 1 :(得分:0)

猜猜这里,但我的猜测是你疯狂地吹嘘你的缓存。您的线程代码有两个变量(xsum)将由所有线程写入,这意味着每个写入都会导致每个其他的高速缓存未命中试图访问这些变量的线程。在这两者中,sum似乎更有问题。

这是基于一个talk by Scott Meyers,他在那里涵盖了一个类似的问题(如果你很好奇的话,它会在谈话的早期)。他的例子表明由于CPU缓存问题导致性能下降。