2017-08-02 132 views
0

我在Linux上編譯一個複雜的C++項目,它使用OpenMP,用CMake和GCC 7編譯。 我在這個特定項目中遇到的奇怪問題OpenMP顯然是在工作,但它認爲只有一個線程被支持,應該是8。但是,如果我手動指定線程數,它確實會加速代碼。omp_get_max_threads()在並行區域返回1,但它應該是8

logOut << "In parallel? " << omp_in_parallel() << std::endl; 
logOut << "Num threads = " << omp_get_num_threads() << std::endl; 
logOut << "Max threads = " << omp_get_max_threads() << std::endl; 

logOut << "Entering my parallel region: " << std::endl; 

//without num_threads(5), only 1 thread is created 
#pragma omp parallel num_threads(5) 
    {   
     #pragma omp single nowait 
     { 
      logOut << "In parallel? " << omp_in_parallel() << std::endl; 
      logOut << "Num threads = " << omp_get_num_threads() << std::endl; 
      logOut << "Max threads = " << omp_get_max_threads() << std::endl; 
     } 
    } 

輸出:

[openmp_test] In parallel? 0 
[openmp_test] Num threads = 1 
[openmp_test] Max threads = 1 
[openmp_test] Entering my parallel region: 
[openmp_test] In parallel? 1 
[openmp_test] Num threads = 5 
[openmp_test] Max threads = 1 

什麼使得它更奇怪的是,一個簡單的測試OpenMP程序直接正確地報告的最大線程數爲8,內部和並行區域之外。 我一直在梳理所有的CMake文件,試圖找到爲什麼這個項目的行爲不同的任何指標,但到目前爲止我沒有發現任何東西。在我的任何項目文件中沒有提及omp_set_num_threads,我可以確認沒有聲明OMP_NUM_THREADS。此外,當我使用MSVC在Windows上編譯相同的項目時,此問題從未發生。

任何想法可能是什麼問題?

(編輯:我已經擴展了代碼示例,以顯示它不是一個嵌套並行塊)

CPU:英特爾(R)核心(TM)i7-6700K

OS:Manjaro Linux的17.0.2

編譯器:GCC 7.1.1 20170630

_OPENMP = 201511(我猜這意味着OpenMP的4.5)

+2

您能否爲您的問題添加特定的平臺信息(操作系統,硬件,編譯器,OpenMP運行庫等)?你也可以嘗試在並行區域之前輸出'omp_in_parallel()'和'omp_get_num_threads()'嗎?您是否還可以驗證您的環境中是否設置了OMP_NUM_THREADS?如果你設置它,你會觀察到不同的行爲嗎? – dlasalle

+0

謝謝,我添加了您建議的信息。我確認並行區域之外的代碼不在並行區域中,並且未聲明「OMP_NUM_THREADS」。 –

+0

您可以嘗試將'getenv(「OMP_NUM_THREADS」);'從調用到程序的開頭以確保它返回NULL嗎?另外,你是否可以擴展你的代碼片段來完成(即,像@FlashMcQueen如何將它包裝在'main()')中,並確認相同的行爲?這將幫助我們排除一些圖書館干擾線程。 – dlasalle

回答

1

,你的程序的行爲完全一樣,如果omp_set_num_線程(1)之前被調用過。

考慮到此片段:

#include <iostream> 
#include <string> 
#include <vector> 
#include "omp.h" 
int main() { 

omp_set_num_threads(1); 

std::cout << "before parallel section: " << std::endl; 
std::cout << "Num threads = " << omp_get_num_threads() << std::endl; 
std::cout << "Max threads = " << omp_get_max_threads() << std::endl; 

//without num_threads(5), only 1 thread is created 
#pragma omp parallel num_threads(5) 
    {   
     #pragma omp single 
     { 
      std::cout << "inside parallel section: " << std::endl; 
      std::cout << "Num threads = " << omp_get_num_threads() << std::endl; 
      std::cout << "Max threads = " << omp_get_max_threads() << std::endl; 
     } 
    } 

    return 0; 
} 

輸出是

before parallel section: 
Num threads = 1  
Max threads = 1 
inside parallel section: 
Num threads = 5 
Max threads = 1 

當我通過(在機器上8)4設置線程數,而不是1運行時,輸出爲預期:

before parallel section: 
Num threads = 1 
Max threads = 4 
inside parallel section: 
Num threads = 5 
Max threads = 4 

您是否嘗試過在你的代碼的開頭調用OMP_SET_NUM_THREADS(8)?或者你在你的程序之前將線程數設置爲1(例如,在一個函數內調用這個...)?

另一個解釋可能是openMP API不需要擁有多個線程,因爲在並行部分內只實現了一個部分。在這種情況下,嘗試添加一些可以由多個線程執行的代碼,以便在單個部分之外但在並行部分之內運行得更快(即遞增大型整數數組的所有值或調用omp_get_thread_num()),並且線程數應該是不同的。調用omp_set_num_threads僅設置所用線程數的上限。

+0

這是有道理的,但地球上可以調用'omp_set_num_threads'?我做了一個完整的搜索,它不會出現在我的代碼中。 –

+0

然後,如果確定未調用omp_set_num_threads(1),則嘗試在單節和並行節內部添加omp_get_thread_num。 (第二種解釋) – FlashMcQueen

+0

已經嘗試過。如果沒有手動設置num_threads,'omp_get_thread_num'始終是0. –

0

您在平行區域內看到的值看起來是正確的(假設OMP_NESTED不正確)。 omp_get_max_threads()返回如果要與當前線程並行,您可能獲得的最大線程數。既然你已經在一個並行區域內(並且我們假設嵌套並行是禁用的),那將是一個並行區域。

3.2.3 omp_get_max_threads

摘要
的omp_get_max_threads例程返回一個上限可用於 以形成一個新的團隊如果遇到沒有NUM_THREADS 子句並行構造的線程數執行從此例程返回後。

這並不能解釋爲什麼你看到並行區域外的值爲1。 (但它確實回答了題目中的問題,答案是「一個是正確答案」)。

相關問題