2

SIMDロード命令を使用してメモリから要素をロードしています。たとえば、Altivecを使用して、アドレスが整列していると仮定しています。

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*/
}

ここで、SIZEがFLOAT_VEC_SIZEの倍数でない場合、最後のループ反復でV0に無効なメモリ要素が含まれている可能性があります。これを回避する1つの方法は、ループを1回繰り返すことです。別の方法は、潜在的な無効な要素をマスクすることです。他に役立つトリックはありますか?上記を考慮すると、ネストされたループのセットの中で最も内側にあります。したがって、SIMD以外の追加の命令には、パフォーマンスの低下が伴います。

4

2 に答える 2

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
}
于 2012-10-23T11:55:37.990 に答える
0

const配列の場合のように、ゼロパディングがオプションではない場合があります。一方、スカラーコードを追加すると、たとえば計算結果を書き戻すときに、ベクトルとスカラーの結果が混在する可能性があります。不要な値をマスクすることは、より良い解決策のように見えます。これは、16バイトのアラインメントを持つアドレスを想定していることに注意してください。おもちゃの例、SIMDベクトルの最後の3つの要素をクリア

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);
于 2012-10-24T15:36:50.057 に答える