2011-02-10 49 views
1

我有一個簡單的圖像處理相關算法。 簡言之,圖像(平均值)在浮子是由一個8位的圖像 結果中減去,然後保存到一個浮動圖像(目標)用TBB優化幾條指令的循環(SSE2,SSE4)

此功能主要是通過寫入內部函數。

我試圖用TBB,par parallel_for, 來優化這個函數,但是我沒有收到速度上的增益,但是沒有受到懲罰。

我該怎麼辦?我是否應該使用更多的低層次方案,如TBB任務 來優化代碼?

float   *m, **m_data, 
       *o, **o_data; 
unsigned char *p, **src_data; 
register unsigned long len, i; 
unsigned long nr, 
       nc; 

src_data = src->UByteData; // 2d array 
m_data  = mean->FloatData; // 2d array 
o_data  = dest->FloatData; // 2d array 
nr   = src->Rows; 
nc   = src->Cols; 

__m128i xmm0; 

for(i=0; i<nr; i++) 
{ 
    m = m_data[i]; 
    o = o_data[i]; 
    p = src_data[i]; 
    len = nc; 
    do 
    { 
     _mm_prefetch((const char *)(p + 16), _MM_HINT_NTA); 
     _mm_prefetch((const char *)(m + 16), _MM_HINT_NTA); 

     xmm0 = _mm_load_si128((__m128i *) (p)); 

     _mm_stream_ps(
         o, 
         _mm_sub_ps(
            _mm_cvtepi32_ps(_mm_cvtepu8_epi32(_mm_srli_si128(xmm0, 0))), 
            _mm_load_ps(m + offset) 
           ) 
        ); 
     _mm_stream_ps(
         o + 4, 
         _mm_sub_ps(
            _mm_cvtepi32_ps(_mm_cvtepu8_epi32(_mm_srli_si128(xmm0, 4))), 
            _mm_load_ps(m + offset + 4) 
           ) 
        ); 
     _mm_stream_ps(
         o + 8, 
         _mm_sub_ps(
            _mm_cvtepi32_ps(_mm_cvtepu8_epi32(_mm_srli_si128(xmm0, 8))), 
            _mm_load_ps(m + offset + 8) 
           ) 
        ); 
     _mm_stream_ps(
         o + 12, 
         _mm_sub_ps(
            _mm_cvtepi32_ps(_mm_cvtepu8_epi32(_mm_srli_si128(xmm0, 12))), 
            _mm_load_ps(m + offset + 12) 
           ) 
        ); 

     p += 16; 
     m += 16; 
     o += 16; 
     len -= 16; 
    } 
    while(len); 
} 
+1

如果IPP已經有這個功能,我不會感到驚訝。 – 2011-02-10 03:05:37

+2

如果您使用的是英特爾編譯器,那麼爲什麼不直接編寫一個該函數的天真版本,並查看編譯器是否可以自行進行矢量化?在這方面我不瞭解GCC。 – 2011-02-10 03:16:13

回答

1

相對於加載和存儲的數量,您在這裏幾乎不做任何計算,所以很可能您受限於內存帶寬而不是計算。這可以解釋爲什麼在優化計算時沒有發現吞吐量有任何改進。

雖然我會擺脫_mm_prefetch指示 - 他們在這裏幾乎肯定沒有幫助,甚至可能會傷害到性能。

如果可能的話,您應該將此循環與您在此之前/之後執行的任何其他操作結合起來 - 這樣您可以通過更多計算來分攤內存I/O的成本。