作者johnjohnlin (LYSin8)
看板C_and_CPP
標題Re: [問題] 如何讓計算速度發揮到極限
時間Thu Aug 15 23:39:32 2013
我剛剛嘗試了一下
平台是
g++, openmp, core i5 2500, linux 64
首先
有人提到 vector 的問題
根據我的測試是這樣(無平行)
L = 1000, 50 iteration
g++ -O2 g++ -g
vec of vec 0.124 1.600
2D array 0.128 0.124
應該是誤差
可見 compiler 很厲害的,只要你有叫他 optimize XDD
第二,我先用 int 來代替你的 double
我認為你的程式的迴圈只要拆外層,要不然會增加不必要的 overhead
#... for
for ()
#... for
<<<這個不需要
for ()
一律用 g++ -O2, 2000 iteration
single thread 5.300
openmp 2.254
omp 拿掉內圈 1.815
你的程式應該沒有 local variable conflict 的問題,所以這部份不考慮
不過把 int 改成 double 的話速度變這樣
single thread 4.098
openmp 懶得編譯...
omp 拿掉內圈 3.567
不會變快,我推論 CPU 的 float point ALU 資源是有上限的......
我猜用 SSE 之類的應該也不會變好?
第三
cache 的問題我想應該還好,但我不確定,因為我也不是很熟 CPU 硬體
CPU 的 cache 我想是 multi-way 的
應該不會因為你同時讀兩個 row 就互相洗掉......
附上程式
#include <vector>
using namespace std;
typedef int TT;
typedef vector<vector<TT> > VVD;
const TT h = 10.0;
void Jacobi(const VVD &V, VVD &VNew, const VVD &rho, const int L)
{
#pragma omp parallel for
for (int i = 1; i < L-1; i++)
#pragma omp parallel for
for (int j = 1; j < L-1; j++)
VNew[i][j] = 0.25 * (V[i - 1][j] + V[i + 1][j] +
V[i][j - 1] + V[i][j + 1] +
h * h * rho[i][j]);
}
void Jacobi_opt(const TT *V, TT *VNew, const TT *rho, const int L)
{
#pragma omp parallel for
for (int i = 1; i < L-1; i++)
#pragma omp parallel for
for (int j = 1; j < L-1; j++)
VNew[i*L+j] = 0.25 * (V[(i-1)*L+j] + V[(i+1)*L+j] +
V[i*L+j-1] + V[i*L+j+1] +
h * h * rho[i*L+j]);
}
int main()
{
int L = 1000;
int N = 2000;
VVD V_v(L);
VVD Vnew_v(L);
VVD rho_v(L);
for (int i = 0; i < L; ++i) {
V_v[i].reserve(L);
Vnew_v[i].reserve(L);
rho_v[i].reserve(L);
for (int j = 0; j < L; ++j) {
V_v[i][j] = rho_v[i][j] = i*L+j;
}
}
TT *V_ptr = new TT[L*L];
TT *Vnew_ptr = new TT[L*L];
TT *rho_ptr = new TT[L*L];
for (int i = 0; i < L*L; ++i) {
V_ptr[i] = rho_ptr[i] = i;
}
for (int i = 0; i < N; ++i) {
if (i&1) {
// Jacobi(Vnew_v, V_v, rho_v, L);
Jacobi_opt(Vnew_ptr, V_ptr, rho_ptr, L);
} else {
// Jacobi(V_v, Vnew_v, rho_v, L);
Jacobi_opt(V_ptr, Vnew_ptr, rho_ptr, L);
}
}
delete[] V_ptr;
delete[] Vnew_ptr;
delete[] rho_ptr;
return 0;
}
※ 引述《Lepton (輕子)》之銘言:
: hi,hi 感謝各位之前熱情的回覆讓我學到用binary方式寫檔案
: 我才發現原來binary的方式這麼好用
: 小的我有另外的問題想請教大家
: 在做流體計算時繁複的計算我都是丟到GPU上計算
: 計算的效率幾乎都是2TLOPs以上,可以發揮到顯示卡計算能力極限的70%左右
: (以GTX680為例2 FLOPS/Clock × 1006 MHz × 1536 = 3.090 TFLOPS)
: 但是同樣的計算放到CPU上都<10GFLOPs,幾乎不到CPU計算能力極限的10%
: (以Ivy Bridge為例 8 FLOPS/Clock × 3.5GHz ×4 = 102.4 GFLOPS )
: 乍看之下GPU好像加速幾乎上百上千倍的計算速度但其實CPU根本沒發揮真本事
: 在GPU的情況編譯器會把乘加合併成一條指令去做才能做到2 FLOPS/Clock
: 那在CPU的部分要啟用SSE指令集或AVX指令集的話是要自己去編寫嗎?還是編譯器會做?
: 因為我在VC2010 中加入/arch:AVX之類的指令但速度並沒有增加
: 我這邊做的事情基本上就是迭代計算
: vector<vector<double> > V, VNew ,rho;
: void Jacobi()
: {
: #pragma omp parallel for
: for (int i = 1; i <= L; i++)
: #pragma omp parallel for
: for (int j = 1; j <= L; j++)
: VNew[i][j] = 0.25 * (V[i - 1][j] + V[i + 1][j] +
: V[i][j - 1] + V[i][j + 1] +
: h * h * rho[i][j]);
: }
--
Time waits for no one.
↑
(。A。)ハァ
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 140.112.217.11
推 littleshan:先推一下實驗精神 08/15 23:56
推 b98901056:強強林必推 08/16 10:23