knc (Xeon Phi) が提供する SIMD 512 を利用して、Intel 組み込み関数を使用して以下の C コードのパフォーマンスを向上させようとしています。ただし、組み込みの組み込みコードは、自動ベクトル化されたコードよりも遅く実行されます
Cコード
int64_t match=0;
int *myArray __attribute__((align(64)));
myArray = (int*) malloc (sizeof(int)*SIZE); //SIZE is array size taken from user
radomize(myArray); //to fill some random data
int searchVal=24;
#pragma vector always
for(int i=0;i<SIZE;i++) {
if (myArray[i]==searchVal) match++;
return match;
組み込みコード: 以下のコードでは、最初に配列をロードし、それを検索キーと比較しています。組み込み関数は、_mm512_mask_reduce_add_epi32() を使用して削減された 16 ビットのマスク値を返します。
register int64_t match=0;
int *myArray __attribute__((align(64)));
myArray = (int*) malloc (sizeof(int)*SIZE); //SIZE is array size taken from user
const int values[16]=\
{ 1,1,1,1,\
1,1,1,1,\
1,1,1,1,\
1,1,1,1,\
};
__m512i const flag = _mm512_load_epi32((void*) values);
__mmask16 countMask;
__m512i searchVal = _mm512_set1_epi32(16);
__m512i kV = _mm512_setzero_epi32();
for (int i=0;i<SIZE;i+=16)
{
// kV = _mm512_setzero_epi32();
kV = _mm512_loadunpacklo_epi32(kV,(void* )(&myArray[i]));
kV = _mm512_loadunpackhi_epi32(kV,(void* )(&myArray[i + 16]));
countMask = _mm512_cmpeq_epi32_mask(kV, searchVal);
match += _mm512_mask_reduce_add_epi32(countMask,flag);
}
return match;
このコードには余分なサイクルが導入されているため、自動ベクトル化されたコードに比べて実行速度が遅いと思います。比較の値を 128 ビット レジスタに直接返す SIMD128 とは異なり、SIMD512 はマスク レジスタに値を返すため、コードがさらに複雑になります。ここで何か不足していますか? XOR ops などのマスクを使用するのではなく、成功した検索のカウントを直接比較して保持する方法が必要です。
最後に、組み込み関数を使用してこのコードのパフォーマンスを向上させる方法を教えてください。組み込み関数を使用して、より多くのパフォーマンスを引き出すことができると信じています。これは少なくとも SIMD128 には当てはまり、組み込み関数を使用することで 25% のパフォーマンスを得ることができました。