[英]GCC OpenMP parallel for reduction MUCH slower than Visual Studio
我和我的一個朋友遇到了有關parallel for reduction
GCC的性能問題。
編碼:
#include <cstdio>
int main() {
int tans = 0;
for (int i = 0; i < 100000; ++i)
#pragma omp parallel for reduction(+:tans)
for (int id = 0; id < 10000; ++id) {
tans++;
}
printf("%d\n", tans);
}
(此無用的代碼僅用於演示問題)
當使用GCC(版本4.9.2(tdm64-1))進行編譯並在我的4核8線程系統(Win 8.1 64b)上運行時,代碼運行大約5s,而使用num_threads(1)
僅運行0.5s。
我還在24核系統(gcc版本4.8.2(Ubuntu 4.8.2-19ubuntu1))上嘗試了相同的代碼,並行版本仍然非常慢,運行時間非常不穩定,范圍從1s到10s 。
使用Visual Studio 2013,代碼總是幾乎立即完成。 生成的匯編代碼可以在這里找到: https : //gist.github.com/ftfish/f8ffdb9106b82ae63925
我做錯了什么? 是因為parallel for reduction
的開銷嗎? 為什么Visual Studio的性能更好? 先感謝您。
如果您的實際代碼與此代碼一樣簡單,則很可能會損失很多編譯器優化的機會。 g++ -O3
為您發布的減去OMP行的代碼生成以下匯編:
.cfi_startproc
subq $8, %rsp
.cfi_def_cfa_offset 16
movl $1000000000, %esi
movl $.LC0, %edi
xorl %eax, %eax
call printf
xorl %eax, %eax
addq $8, %rsp
.cfi_def_cfa_offset 8
ret
正如你看到的,絕對沒有什么在這里是在運行時計算,其循環都完全優化掉。 這樣,程序立即完成。 如果讓計算在運行時進行,顯然會增加它。 在這里,您可以看到添加OMP行實際上使計算在運行時發生,生成的程序集太長而無法粘貼到此處。
編輯:
我用g ++和clang ++都測試了OMP代碼,並且可以重現您的問題(g ++大約0.3s,clang ++ 0.006s,即即時)。 clang確實優化了兩個循環,即使使用OMP線也是如此。 由於您的代碼非常完美,因此這是gcc優化器的錯誤。 現在還不清楚gcc伙計們是否搞砸了,或者是否遵循了諸如“如果用戶編寫OMP,他應該通過測量並行版本更快來發現它。不要對其進行優化”之類的道理。 我會把錢花在后者上,但如果要確定的話,請訪問gcc bugzilla。
剩下的就是我在評論中提到的結論: 衡量一切。
在這種特殊情況下:如果要定位gcc和VC,只需在兩種環境中同時測量兩種變體,然后將更好的一種寄給客戶。 如果您認為這是gcc性能錯誤,則仍可以為他們編寫錯誤報告。
最后一句話:
如果您的實際代碼是像這樣的雙循環,請考慮並行處理最外面的代碼,以節省昂貴的OMP啟動過程(但是measure(!),這當然可能無濟於事。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.