簡體   English   中英

OpenMP:Visual C ++ 2008和2010之間的巨大性能差異

[英]OpenMP: Huge performance differences between Visual C++ 2008 and 2010

我正在運行一個攝像頭采集程序,對采集的圖像進行處理,我正在使用簡單的OpenMP指令進行處理。 所以基本上我等待來自相機的圖像,然后處理它。

遷移到VC2010時,我看到了非常奇怪的性能問題:在VC2010下,我的應用程序占用了近100%的CPU,而在VC2008下只占用了10%。

如果我只對處理代碼進行基准測試,那么VC2010和VC2008之間沒有區別,使用采集功能會產生差異。

我已經將重現問題所需的代碼減少到一個簡單的循環,執行以下操作:

  for (int i=0; i<1000; ++i)
  {
    GetImage(buffer);//wait for image
    Copy2Array(buffer, my_array);

    long long sum = 0;//do some simple OpenMP parallel loop
    #pragma omp parallel for reduction(+:sum)
    for (int j=0; j<size; ++j)
      sum += my_array[j];
  }

這個循環占2008年CPU的5%,2010年占70%。

我做了一些分析,這表明在2010年大部分時間花在OpenMP的vcomp100.dll!_vcomp::PartialBarrierN::Block

我還做了一些並發性分析:

在2008年,處理工作分布在3個工作線程上,由於處理時間遠遠低於圖像等待時間,所以它們非常活躍

相同的線程出現在2010年,但它們都被PartialBarrierN::Block函數100%占用。 由於我有四個核心,他們正在吃75%的工作,這大致是我在CPU職業中看到的。

所以看起來OpenMP和Matrox采集庫(專有)之間存在沖突。 但它是VS2010或Matrox的錯誤嗎? 有什么我能做的嗎? 使用VC ++ 2010對我來說是必須的,所以我不能堅持使用2008。

太謝謝了

狀態更新

正如DeadMG所建議的那樣,使用新的並發框架會導致40%的CPU。 分析它顯示時間花在處理上,因此它沒有顯示我在OpenMP中看到的錯誤,但在我的情況下性能比OpenMP差。

狀態更新2

我已經安裝了最新英特爾C ++的評估版。 它顯示完全相同的性能問題!!

我交叉發布到MSDN論壇

狀態更新3

在Windows 7 64位和XP 32位上測試,結果完全相同(在相同的機器上)

在2010 OpenMP中,每個工作線程在任務完成后執行大約200 ms的旋轉等待。 在我的I / O等待和重復的OpenMP任務的情況下,它正在大量加載CPU。

解決方案是改變這種行為; 英特爾C ++有一個擴展例程 ,即kmp_set_blocktime() 但是Visual 2010沒有這種可能性。

這篇Autodesk筆記中,他們討論了英特爾C ++的問題。 此編譯器首先引入了該行為,但允許更改它(參見上文)。 Visual 2010切換到它,但......沒有像英特爾這樣的解決方法。

總而言之,切換到英特爾C ++並使用kmp_set_blocktime(0)解決了它。

感謝DataLever公司的 John Lilley在另一個MSDN線程上

問題已提交給MS Connect ,並收到“無法修復”的反饋。

使用OpenMP 3.0,可以通過OMP_WAIT_POLICY停用spinwait:

_putenv_s( "OMP_WAIT_POLICY", "PASSIVE" );

效果與kmp_set_blocktime(0)基本相同,但是當我們在運行時設置環境變量OMP_WAIT_POLICY時,它只會影響當前進程和子進程。

當然,OMP_WAIT_POLICY也可以由啟動器應用程序設置,例如Blender以這種方式處理它。

此處提供VC2010的修補程序,VC2013等更高版本可直接支持。

您可以嘗試使用VS2010附帶的新並發運行時 - 只需從測試樣本開始。

那是,

for (int i=0; i<1000; ++i)
  {
    GetImage(buffer);//wait for image
    Copy2Array(buffer, my_array);

    long long sum = 0;//do some simple OpenMP parallel loop
    #pragma omp parallel for reduction(+:sum)
    for (int j=0; j<size; ++j)
      sum += my_array[j];
  }

會成為

for (int i=0; i<1000; ++i)
  {
    GetImage(buffer);//wait for image
    Copy2Array(buffer, my_array);

    Concurrency::combinable<int> combint;
    Concurrency::parallel_for(0, size / 1000, [&](int j) {
      for(int i = 0; i < 1000; i++)
          combint.local() += my_array[(j * 1000) + i];
    });
    combint.combine([](int a, int b) { return a + b; });
  }

我測試了另一個采集板,問題是相同的,所以罪魁禍首是VC ++ 2010。 正如MSDN論壇上的一個帖子所示,微軟做了一些OpenMP實現更改,搞砸了像我這樣的程序。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM