我一直在使用一段密集的內存綁定代碼。我試圖通過手動實現緩存阻塞,sw預取,循環展開等在單個內核中對其進行優化。儘管緩存阻塞可顯着提高性能。但是,當我介紹循環展開時,我得到了巨大的性能下降。循環展開對內存綁定數據的影響
我編譯與英特爾ICC與編譯器標誌-02和我所有的測試用例-ipo。
我的代碼是與此類似(3D 25點模版):
void stencil_baseline (double *V, double *U, int dx, int dy, int dz, double c0, double c1, double c2, double c3, double c4)
{
int i, j, k;
for (k = 4; k < dz-4; k++)
{
for (j = 4; j < dy-4; j++)
{
//x-direction
for (i = 4; i < dx-4; i++)
{
U[k*dy*dx+j*dx+i] = (c0 * (V[k*dy*dx+j*dx+i]) //center
+ c1 * (V[k*dy*dx+j*dx+(i-1)] + V[k*dy*dx+j*dx+(i+1)])
+ c2 * (V[k*dy*dx+j*dx+(i-2)] + V[k*dy*dx+j*dx+(i+2)])
+ c3 * (V[k*dy*dx+j*dx+(i-3)] + V[k*dy*dx+j*dx+(i+3)])
+ c4 * (V[k*dy*dx+j*dx+(i-4)] + V[k*dy*dx+j*dx+(i+4)]));
}
//y-direction
for (i = 4; i < dx-4; i++)
{
U[k*dy*dx+j*dx+i] += (c1 * (V[k*dy*dx+(j-1)*dx+i] + V[k*dy*dx+(j+1)*dx+i])
+ c2 * (V[k*dy*dx+(j-2)*dx+i] + V[k*dy*dx+(j+2)*dx+i])
+ c3 * (V[k*dy*dx+(j-3)*dx+i] + V[k*dy*dx+(j+3)*dx+i])
+ c4 * (V[k*dy*dx+(j-4)*dx+i] + V[k*dy*dx+(j+4)*dx+i]));
}
//z-direction
for (i = 4; i < dx-4; i++)
{
U[k*dy*dx+j*dx+i] += (c1 * (V[(k-1)*dy*dx+j*dx+i] + V[(k+1)*dy*dx+j*dx+i])
+ c2 * (V[(k-2)*dy*dx+j*dx+i] + V[(k+2)*dy*dx+j*dx+i])
+ c3 * (V[(k-3)*dy*dx+j*dx+i] + V[(k+3)*dy*dx+j*dx+i])
+ c4 * (V[(k-4)*dy*dx+j*dx+i] + V[(k+4)*dy*dx+j*dx+i]));
}
}
}
}
當我做循環展開上最內層循環(尺寸i)和在方向x,y展開,Z分別由UNROLL因子分別爲2,4,8,在所有9種情況下,我的性能都有所下降,即在方向x上展開2,在方向y上展開2,在方向z上展開2,在方向x上展開4 ...等。 但是當我在最外層循環(維k)上循環展開係數8(也是)時,我得到的性能改進甚至比緩存阻塞更好。
我甚至嘗試剖析我的代碼以英特爾VTune。這似乎是主要由於1.LLC Miss和2. LLC負載未命中由遠程DRAM服務的瓶頸。
我無法理解爲什麼在給性能下降而展開的最外層,最慢的維度獲取的性能提升展開的最裏面最快的循環。然而,在後一種情況下的這種改進是當我使用-O2和-ipo編譯icc時。
我不知道如何解釋這些統計數據。有人可以幫助闡明這一點。
另一方面:大概編譯器正在優化k * dy * dx爲temp? –
@Mitch小麥:我使用通用的子表達式消除,在我的原始代碼中考慮到k * dx * dy和j * dx。這是更多的示例代碼 – Anusuya
你可以使用SSE指令來計算一些嗎?從快速瀏覽它看起來可以... – sarnold