2012-06-22 66 views
1

我正在嘗試僅使用對齊,加載和存儲向量化2D模板。爲此,我想主要使用_mm_load_ps_mm_shuffle_ps來獲取所需的地址。使用SSE內在函數向量化2D模板

我的代碼標版本是:

void FDTD_base (float *V, float *U, int dx, int dy, float c0, float c1, float c2, float c3, float c4) 
    { 
    int i, j, k; 

      for (j = 4; j < dy-4; j++) 
      { 
        for (i = 4; i < dx-4; i++) 
        { 

          U[j*dx+i] = (c0 * (V[j*dx+i]) //center 
            + c1 * (V[j*dx+(i-1)] + V[(j-1)*dx+i] + V[j*dx+(i+1)] + V[(j+1)*dx+i]) 
            + c2 * (V[j*dx+(i-2)] + V[(j-2)*dx+i] + V[j*dx+(i+2)] + V[(j+2)*dx+i]) 
            + c3 * (V[j*dx+(i-3)] + V[(j-3)*dx+i] + V[j*dx+(i+3)] + V[(j+3)*dx+i]) 
            + c4 * (V[j*dx+(i-4)] + V[(j-4)*dx+i] + V[j*dx+(i+4)] + V[(j+4)*dx+i])); 

        } 
      } 

     } 

我的矢量看到的代碼版本至今:

 for (j = 4; j < dy-4; j++) 
    { 
      for (i = 4; i < dx-4; i+=4) 
      { 
        __m128 b = _mm_load_ps(&V[j*dx+i]); 
        center = _mm_mul_ps(b,c0_i); 
        a = _mm_load_ps(&V[j*dx+(i-4)]); 
        c = _mm_load_ps(&V[j*dx+(i+4)]); 

        d = _mm_load_ps(&V[(j-4)*dx+i]); 
        e = _mm_load_ps(&V[(j+4)*dx+i]); 

        u_i2 = _mm_shuffle_ps(a,b,_MM_SHUFFLE(1,0,3,2));//i-2 
        u_i6 = _mm_shuffle_ps(b,c,_MM_SHUFFLE(1,0,3,2));//i+2 

        u_i1 = _mm_shuffle_ps(u_i2,b,_MM_SHUFFLE(2,1,2,1));//i-1 
        u_i5 = _mm_shuffle_ps(b,u_i6,_MM_SHUFFLE(2,1,2,1));//i+1 

        u_i3 = _mm_shuffle_ps(a,u_i2,_MM_SHUFFLE(2,1,2,1));//i-3 
        u_i7 = _mm_shuffle_ps(u_i6,c,_MM_SHUFFLE(2,1,2,1));//i+3 

        u_i4 = a; //i-4 
        u_i8 = c; //i+4 

有人可以幫助我獲得J-1的位置,J + 1 ..... J-4,J + 4。

這不起作用:

    u_j2 = _mm_shuffle_ps(d,b,_MM_SHUFFLE(1,0,3,2));//j-2 (this is incorrect) 
        u_j6 = _mm_shuffle_ps(b,e,_MM_SHUFFLE(1,0,3,2));//j+2 

        u_j1 = _mm_shuffle_ps(u_j2,b,_MM_SHUFFLE(2,1,2,1));//j-1 
        u_j5 = _mm_shuffle_ps(b,u_j6,_MM_SHUFFLE(2,1,2,1));//j+1 

        u_j3 = _mm_shuffle_ps(d,u_j2,_MM_SHUFFLE(2,1,2,1));//j-3 
        u_j7 = _mm_shuffle_ps(u_j6,e,_MM_SHUFFLE(2,1,2,1));//j+3 

        u_j4 = d; //j-4 (this is fine) 
        u_j8 = e; //j+4 

我只需要幫助確定如何獲得(j-1)*dx+i(j+1)*dx+1 ..... (j-4)*dx+i(j+4)*dx+i不使用未對齊的負荷。

作爲一個潛在的解決方案,我想增加一個位移3*dx存儲在d存儲的地址,以獲得(j-1)*dx+i。並且將3*dx的位移減去存儲在e中的地址以獲得(j+1)*dx+i。 同樣加入2*dx到地址d獲得j-2等等。但我不知道使用SSE內在函數來實現這個策略。

請幫忙。我正在使用Intel icc編譯器。

+0

[由於錯誤的內存對齊而與SSE內部函數一起工作時出現分段錯誤]的可能重複(http://stackoverflow.com/questions/11085924/segmentation-fault-while-working-with-sse-intrinsics-due-to -incorrect-memory-ali) –

+0

@Paul:不完全。當涉及到跨度值時,我試圖確定如何使用'mm_shuffle_ps'。上一篇文章是針對一維滑動窗口的。這是一個2D滑動窗口,它有一個新的維度,這使得它更加複雜。任何幫助將非常有幫助 – PGOnTheGo

+0

您的所有約束都很牢固嗎?例如,絕對沒有未對齊的加載和存儲?還有其他表達相同計算的方式(尤其是Nehalem和後來的Intel CPU),但確實需要未對齊的加載和存儲。 –

回答

0

「有人可以幫助我獲得j-1,j + 1 ..... j-4,j + 4的位置。」 - 這些不需要洗牌;他們已經與您的SIMD車道保持一致。

u_j2 = _mm_load_ps(&V[(j-2)*dx+i]); 
u_j6 = _mm_load_ps(&V[(j+2)*dx+i]); 
u_j1 = _mm_load_ps(&V[(j-1)*dx+i]); 
u_j5 = _mm_load_ps(&V[(j+1)*dx+i]); 
// and so forth 

絕對不能將這些從您通過任何可能的重,因爲值d(例如)是V[j-4, i], V[j-4, i+1], V[j-4, i+2], V[j-4, i+3],而你不能得到V[j-2, i]出的是,標爲de的變量。提示:從SIMD通道角度考慮;這表明你需要重新排列而不是垂直排列。

提示:考慮內循環計數器增量時會發生什麼(i+=4)。最後一個循環中的u_i5(V[j, i+1..i+5])現在是當前循環中的u_i3(V[j, i-3..i+1])。您正在計算行中數據的每個偏移版本至少兩次。你可以展開幾次循環,避免做所有額外的工作。

提示:爲什麼不使用AVX?使用_mm256_permute_ps(和_mm256_permute2f128_ps,如果需要)進行隨機播放,以及相應的加載指令。由於SIMD寄存器的寬度是兩倍,並且大多數AVX指令在現代CPU上仍然只佔用一個週期,與SSE指令相同,所以速度將快兩倍。

+0

@你好:請看看,讓我知道這是否回答你的問題。如果是這樣,如果您接受並讚揚,我將不勝感激。謝謝! –