我使用SIMD计算快速指数结果。我比较非SIMD代码的时间。乘方是使用正方形和乘法算法来实现。

普通(非SIMD)的代码版本:

b = 1;  
for (i=WPE-1; i>=0; --i){  
    ew = e[i];  
    for(j=0; j<BPW; ++j){  
        b = (b * b) % p;  
        if (ew & 0x80000000U)  b = (b * a) % p;  
        ew <<= 1;  
    }  
}  

SIMD版本:

   B.data[0] = B.data[1] = B.data[2] = B.data[3] = 1U;  
   P.data[0] = P.data[1] = P.data[2] = P.data[3] = p;  
   for (i=WPE-1; i>=0; --i) {  
      EW.data[0] = e1[i]; EW.data[1] = e2[i]; EW.data[2] = e3[i]; EW.data[3] = e4[i];  
      for (j=0; j<BPW;++j){  
         B.v *= B.v; B.v -= (B.v / P.v) * P.v;  
         EWV.v = _mm_srli_epi32(EW.v,31);  
         M.data[0] = (EWV.data[0]) ? a1 : 1U;  
         M.data[1] = (EWV.data[1]) ? a2 : 1U; 
         M.data[2] = (EWV.data[2]) ? a3 : 1U; 
         M.data[3] = (EWV.data[3]) ? a4 : 1U;  
         B.v *= M.v; B.v -= (B.v / P.v) * P.v;  
         EW.v = _mm_slli_epi32(EW.v,1);  
      }  
   } 

的问题是尽管它是正确的计算,SIMD版本花费更多的时间比非SIMD版本。

请帮我调试的原因。上SIMD编码任何建议也受欢迎。

感谢和问候, 阿努普。

有帮助吗?

解决方案

for循环中所有的功能应该是SIMD功能,而不是只有两个。时间服用设置参数为您的2个功能是不太理想那么你的原始实例(其最有可能由编译器优化)

其他提示

一个SIMD环32位的int数据通常看起来像这样:

for (i = 0; i < N; i += 4)
{
    // load input vector(s) with data at array index i..i+3
    __m128 va = _mm_load_si128(&A[i]);
    __m128 vb = _mm_load_si128(&B[i]);

    // process vectors using SIMD instructions (i.e. no scalar code)
    __m128 vc = _mm_add_epi32(va, vb);

    // store result vector(s) at array index i..i+3
    _mm_store_si128(&C[i], vc);
}

如果你发现你所需要的循环内标码和SIMD代码之间移动,那么你可能不会得到来自SIMD优化任何东西。

在许多编程SIMD的功力来自想尽办法把你的算法工作,支持的指令和数据类型,一个给定的SIMD架构提供的数量有限。你会经常需要利用的的先验的数据集的知识,以获得最佳的性能,例如如果你肯定知道你的32个整型值实际上有一定范围的16位之内配合,那么这将让你的算法有很多更容易实现的乘法部分。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top