OpenMP线程在同一个cpu核心上执行

时间:2012-02-21 01:06:44

标签: c++ linux openmp virtualbox

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

#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次似乎使用所有4个内核判断cpu利用率(以及系统变得非常无响应的事实) 。

所以我的问题基本上就是这里究竟发生了什么。更重要的是: 我的推论是否所有线程都正确使用相同的核心?如果是,那可能是什么原因?

4 个答案:

答案 0 :(得分:6)

经过一些实验,我发现问题在于我是从eclipse IDE中启动我的程序,这似乎设置了仅使用一个核心的亲和力。我认为从IDE外部启动时遇到了同样的问题,但重复测试表明程序运行正常,从终端启动而不是从ide内部启动。

答案 1 :(得分:2)

我在Linux上使用g ++ 4.6编译了你的程序

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)应该意味着程序能够看到4个可用的CPU。我无法猜测为什么它没有使用它们但我怀疑你的硬件/软件设置,某些环境变量或编译器选项中存在问题。

答案 2 :(得分:0)

您应该使用#pragma omp parallel for
是的,你是不对的,不需要OMP_NUM_THREADS。 omp_set_num_threads(4);也应该做得很好。

答案 3 :(得分:0)

如果您在Windows上运行,请尝试以下方法:

c:\ windows \ system32 \ cmd.exe / C start / affinity F path \ to \ your \ program.exe

/ affinity 1使用CPU0

/ affinity 2使用CPU1

/ affinity 3使用CPU0和CPU1

/ affinity 4使用CPU2

/ affinity F使用全部4个核心

将数字转换为十六进制,并查看右边的位,这些位是要使用的核心。

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