在KNC(Xeon Phi)中查找向量数组中的数字实例

时间:2014-02-15 05:20:53

标签: c simd intrinsics xeon-phi

我正在尝试利用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%的性能。

1 个答案:

答案 0 :(得分:1)

我建议进行以下优化:

  • 使用预取。您的代码执行很少的计算,几乎肯定是带宽限制。 Xeon Phi仅为L2缓存提供硬件预取,因此为了获得最佳性能,您需要手动插入预取指令。
  • 使用@PaulR暗示的对齐读取_mm512_load_epi32。使用memalign函数而不是malloc来保证数组在64字节上实际对齐。如果您需要未对齐的指令,请使用_mm512_undefined_epi32()作为第一个未对齐加载的源,因为它会破坏对kV的依赖(在当前代码中)并让编译器执行其他优化。 / LI>
  • 将数组展开2或使用至少两个线程来隐藏指令延迟。
  • 避免使用int变量作为索引。 unsigned intsize_tssize_t是更好的选择。