2012-02-21 93 views
7

我目前在4核心Phenom2上使用openmp并行化程序。但是我注意到我的并行化对性能没有任何作用。当然,我认为我错过了一些东西(falsesharing,通过锁序列化,...),但我无法找到这样的事情。此外,从CPU利用率看来,程序似乎只在一个内核上执行。从我发现sched_getcpu()应该给我的核心线程执行调用目前的计划。所以我写了下面的测试程序:OpenMP线程在相同的CPU核心上执行

#include <iostream> 
#include <sstream> 
#include <omp.h> 
#include <utmpx.h> 
#include <random> 
int main(){ 
    #pragma omp parallel 
    { 
     std::default_random_engine rand; 
     int num = 0; 
    #pragma omp for 
     for(size_t i = 0; i < 1000000000; ++i) num += rand(); 
    auto cpu = sched_getcpu(); 
    std::ostringstream os; 
     os<<"\nThread "<<omp_get_thread_num()<<" on cpu "<<sched_getcpu()<<std::endl; 
     std::cout<<os.str()<<std::flush; 
    std::cout<<num; 
    } 
} 

在我的机器这让下面的输出(随机数会有所不同,当然):

Thread 2 on cpu 0 num 127392776 
Thread 0 on cpu 0 num 1980891664 
Thread 3 on cpu 0 num 431821313 
Thread 1 on cpu 0 num -1976497224 

从这个我认为所有的线程上执行相同的核心(具有ID 0的核心)。为了更确定我还尝试了从this answer的方法。结果在哪里相同。另外使用#pragma omp parallel num_threads(1)并没有使执行速度变慢(实际上稍微快一点),这使得所有线程都使用相同cpu的理论具有可信性,但是cpu始终显示为0这一事实让我有点怀疑。另外我检查了GOMP_CPU_AFFINITY最初没有设置,所以我尝试将它设置为0 1 2 3,它应该将每个线程绑定到我了解的不同内核。但是这并没有什么区别。

由于在windows系统上开发,我在virtualbox中使用linux进行开发。所以我尽管可能虚拟系统无法访问所有内核。然而,检查virtualbox的设置表明,虚拟机应该获得所有4个内核,并同时执行4次测试程序,似乎从CPU利用率(以及系统变得非常没有响应的事实)来看,所有4个内核都可以使用, 。

所以对于我的问题基本上究竟是在这里发生了什么。更重要的是: 我的推论是所有线程都正确地使用相同的内核?如果是这样,那么行为的原因是什么?

+1

继承人您设置了环境变量OMP_NUM_THREADS = 4的常见错误吗? – pyCthon 2012-02-21 01:18:38

+0

@pyCthon:'OMP_NUM_THREADS'似乎没有被设置,但是因为openmp确实创建了4个线程,所以我不认为我需要。 – Grizzly 2012-02-21 01:22:04

+0

奇怪我认为它可能是你的虚拟机的东西,我试过甚至安装了utmpx.h的代码,它似乎在8和16核心机器上工作正常 – pyCthon 2012-02-21 01:58:55

回答

6

经过一番实验后,我发现问题在于我从eclipse IDE中启动了我的程序,该IDE似乎将亲和力设置为只使用一个核心。当我从IDE之外开始时,我认为我遇到了同样的问题,但重复测试表明,该程序在从终端而不是IDE内部启动时运行良好。

0

你应该使用#pragma omp parallel for
是的,你说的不需要OMP_NUM_THREADS。 omp_set_num_threads(4);也应该没问题。

+0

为什么我要用'#pragma omp parallel for',如果我想让线程在循环之外做一些事情(比如将它们的id写到输出中)?正如我所提到的,它默认创建4个线程,似乎在同一个核心上执行 – Grizzly 2012-02-21 14:36:59

+0

这也是如此。顺便说一句,如果你不说omp * parallel * for,那么在循环中不会发生并行化。但是,当然你在一个平行部分内,所以......我能想到的唯一其他可能的解释是虚拟机缺少硬件支持。您是否尝试过使用其他CPU? http://superuser.com/questions/33723/getting-2-processors-to-work-with-virtualbox-on-dual-core-celeron – Nav 2012-02-22 03:19:05

+0

我没有。但是如前所述,可以使用vbox中的所有核心,因此缺乏支持似乎不太可能 – Grizzly 2012-02-23 16:16:51

0

,如果你在Windows上运行,试试这个:

C:\ WINDOWS \ SYSTEM32 \ CMD.EXE/C开始/亲和力F轨迹\到\你\ Program.exe文件

/亲和力1使用CPU0

/亲和2使用CPU1

/亲和3使用CPU0和CPU1

/亲和4使用CPU2

/亲和力˚F使用所有4个内核

转换数为十六进制,并查看右侧将被使用的核的位。

您可以使用任务管理器验证其运行时的亲和性。

+0

vbox确实具有使用所有核心的正确亲和力(我检查过,除此之外它如何在我的测试中使用所有核心我的测试程序开始)。因为我在vbox中使用linux并不真正有帮助。 – Grizzly 2012-02-21 14:38:44

1

我用g ++编译你的程序4。6在Linux上

g++ --std=c++0x -fopenmp test.cc -o test 

输出是勿庸置疑:

Thread 2 on cpu 2 

Thread 3 on cpu 1 
910270973 
Thread 1 on cpu 3 
910270973 
Thread 0 on cpu 0 
910270973910270973 

是4个线程启动(如果您没有设置任何形式的线程数,使用OMP_NUM_THREADS EG),这一事实应该意味着该程序能够看到4个可用的CPU。我无法猜测它为什么不使用它们,但我怀疑硬件/软件设置,某些环境变量或编译器选项中存在问题。