我正在尝试利用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;
内在嵌入代码: 在下面的代码中,我首先加载数组并将其与搜索键进行比较。 Intrinsics返回使用_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操作等掩码。
最后,请建议我使用内在函数提高此代码性能的方法。我相信我可以使用内在函数来提高性能。对于SIMD128来说至少是这样,使用内在函数可以让我获得25%的性能。
答案 0 :(得分:1)
我建议进行以下优化:
_mm512_load_epi32
。使用memalign
函数而不是malloc
来保证数组在64字节上实际对齐。如果您需要未对齐的指令,请使用_mm512_undefined_epi32()
作为第一个未对齐加载的源,因为它会破坏对kV
的依赖(在当前代码中)并让编译器执行其他优化。 / LI>
int
变量作为索引。 unsigned int
,size_t
或ssize_t
是更好的选择。