2012-10-23 47 views
2

我使用SIMD加載指令從存儲器加載元素,讓說使用AltiVec技術,假設對齊地址:避免與SIMD指令無效的內存負載

float X[SIZE]; 
vector float V0; 
unsigned FLOAT_VEC_SIZE = sizeof(vector float); 
for (int load_index =0; load_index < SIZE; load_index+=FLOAT_VEC_SIZE) 
{ 
    V0 = vec_ld(load_index, X); 
    /* some computation involving V0*/ 
} 

現在,如果大小不是FLOAT_VEC_SIZE的倍數,可以V0在最後一次循環迭代中包含一些無效的內存元素。避免的方法之一是通過一個迭代,以減少環路,另一個是屏蔽掉的潛在無效元素,有沒有其他有用的技巧嗎?考慮到上面是一組嵌套循環中的最內層。因此,任何額外的非SIMD指令都會帶來性能損失!

回答

2

理想情況下,您應該將您的陣列填充到vec_step(vector float)(即4個元素的倍數)的倍數,然後屏蔽掉SIMD處理中的任何其他不需要的值或使用標量代碼來處理最後幾個元素。

const INT VF_ELEMS = vec_step(vector float); 
const int VEC_SIZE = (SIZE + VF_ELEMS - 1)/VF_ELEMS; // number of vectors in X, rounded up 
vector float VX[VEC_SIZE]; // padded array with 16 byte alignment 
float *X = = (float *)VX; // float * pointer to base of array 

for (int i = 0; i <= SIZE - VF_ELEMS; i += VF_ELEMS) 
{       // for each full SIMD vector 
    V0 = vec_ld(0, &X[i]); 
    /* some computation involving V0 */ 
} 
if (i < SIZE)    // if we have a partial vector at the end 
{ 
#if 1      // either use SIMD and mask out the unwanted values 
    V0 = vec_ld(0, &X[i]); 
    /* some SIMD computation involving partial V0 */ 
#else      // or use a scalar loop for the remaining 1..3 elements 
    /* small scalar loop to handle remaining points */ 
#endif 
} 
+0

感謝您的留言,但我不認爲對齊是這裏的一個問題。我們說,有在X 7組的元素,所以vec_ld(0,X)將帶來前四「漂浮」,而vec_ld(4,X)將返回3個有效元素,同時還有第四難保,不是嗎? – fsheikh

+0

對不起 - 我錯過了有關SIZE不是FLOAT_VEC_SIZE倍數的部分 - 我馬上更新我的答案。 –

0

有時零填充不是一個選項,因爲在常量數組的情況下。另一方面,添加標量代碼可能會導致向量和標量結果的混合,例如,在寫回計算結果時;掩蓋不需要的值看起來是更好的解決方案。請注意,這假定地址爲16字節對齊。 玩具的例子,清除SIMD矢量的最後三個元素

vector bool int V_MASK = (vector bool int) {0,0,0,0}; 
unsigned int all_ones = 0xFFFFFFFFFFFFFFFF; 
unsigned int * ptr_mask = (unsigned int *) &V_MASK; 
ptr_mask[0]= all_ones; 
vector float XV = vec_ld(0,some_float_ptr); 
XV = vec_and(XV,V_MASK);