簡體   English   中英

C++ 與 OpenMP 嘗試避免緊密循環數組的錯誤共享

[英]C++ with OpenMP try to avoid the false sharing for tight looped array

我嘗試將 OpenMP 引入到我的 c++ 代碼中,以使用如下所示的簡單案例來提高性能:

#include <omp.h>
#include <chrono>
#include <iostream>
#include <cmath>

using std::cout;
using std::endl;

#define NUM 100000

int main()
{
    double data[NUM] __attribute__ ((aligned (128)));;

    #ifdef _OPENMP
        auto t1 = omp_get_wtime();
    #else
        auto t1 = std::chrono::steady_clock::now();
    #endif

    for(long int k=0; k<100000; ++k)
    {

        #pragma omp parallel for schedule(static, 16) num_threads(4)
        for(long int i=0; i<NUM; ++i)
        {
            data[i] = cos(sin(i*i+ k*k));
        }
    }

    #ifdef _OPENMP
        auto t2 = omp_get_wtime();
        auto duration = t2 - t1;
        cout<<"OpenMP Elapsed time (second): "<<duration<<endl;
    #else
        auto t2 = std::chrono::steady_clock::now();
        auto duration = std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1).count();
        cout<<"No OpenMP Elapsed time (second): "<<duration/1e6<<endl;
    #endif

    double tempsum = 0.;
    for(long int i=0; i<NUM; ++i)
    {
        int nextind = (i == 0 ? 0 : i-1);
        tempsum += i + sin(data[i]) + cos(data[nextind]);
    }
    cout<<"Raw data sum: "<<tempsum<<endl;
    return 0;    
}

訪問緊密循環的 int 數組(大小 = 10000)並以並行或非並行方式更改其元素。

構建為

g++ -o test test.cpp 

或者

g++ -o test test.cpp -fopenmp

該程序報告的結果如下:

No OpenMP Elapsed time (second): 427.44
Raw data sum: 5.00009e+09

OpenMP Elapsed time (second): 113.017
Raw data sum: 5.00009e+09

英特爾第 10 代 CPU,Ubuntu 18.04,GCC 7.5,OpenMP 4.5。

我懷疑緩存行中的錯誤共享導致OpenMP版本代碼性能不佳。

我在增加循環大小后更新了新的測試結果,OpenMP 運行速度如預期的那樣快。

謝謝!

  1. 由於您正在編寫 C++,因此請使用 C++ 隨機數生成器,它線程安全的,與您正在使用的 C 遺留生成器不同。
  2. 此外,您沒有使用數據數組,因此編譯器實際上可以自由地完全刪除循環。
  3. 在執行定時循環之前,您應該觸摸所有數據一次。 通過這種方式,您可以確保頁面被實例化並且數據在緩存中或緩存外取決於。
  4. 你的循環很短。
  1. rand()不是線程安全的(參見此處)。 請改用一組 C++ 個隨機數生成器,每個線程一個。 有關詳細信息,請參見std::uniform_int_distribution
  2. 您可以在代碼中刪除#ifdef _OPENMP變體。 在 Bash 終端中,您可以將您的應用程序調用為OMP_NUM_THREADS=1 test 有關詳細信息,請參見此處
  3. 因此,您也可以刪除num_threads(4) ,因為您可以明確指定並行度。
  4. 使用Google Benchmark或命令行參數,以便您可以參數化線程數和數組大小。

從這里,我希望你會看到:

  1. 調用OMP_NUM_THREADS=1 test時的性能接近非 OpenMP 版本。
  2. C++ RNG 生成器的數組比從多個線程調用rand()更快。
  3. 在使用 10,000 個元素的數組時,多線程版本仍然比單線程版本慢。

暫無
暫無

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

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