2012-02-21 91 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。我無法猜測它爲什麼不使用它們,但我懷疑硬件/軟件設置,某些環境變量或編譯器選項中存在問題。