我嘗試將 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 運行得比預期的更快。
謝謝!
uj5u.com熱心網友回復:
- 由于您正在撰寫 C ,因此請使用 C 亂數生成器,它是執行緒安全的,與您正在使用的 C 傳統生成器不同。
- 此外,您沒有使用資料陣列,因此編譯器實際上可以完全洗掉您的回圈。
- 在執行定時回圈之前,您應該觸摸一次所有資料。這樣,您可以確保頁面被實體化并且資料根據快取進出快取。
- 你的回圈很短。
uj5u.com熱心網友回復:
rand()不是執行緒安全的(見這里)。改為使用一組 C 亂數生成器,每個執行緒一個。詳情請參閱std::uniform_int_distribution。- 您可以洗掉
#ifdef _OPENMP代碼中的變體。在 Bash 終端中,您可以將應用程式稱為OMP_NUM_THREADS=1 test. 有關詳細資訊,請參見此處。 - 因此,您也可以洗掉
num_threads(4),因為您可以明確指定并行度。 - 使用Google Benchmark或命令列引數,您可以引數化執行緒數和陣列大小。
從這里,我希望你會看到:
- 呼叫時的性能
OMP_NUM_THREADS=1 test接近非 OpenMP 版本。 rand()C RNG 生成器陣列比從多個執行緒呼叫更快。- 在使用 10,000 個元素的陣列時,多執行緒版本仍然比單執行緒版本慢。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/451015.html
上一篇:將字串轉換為ByteBuffer
