C 用于求幂运算的SIMD代码

C 用于求幂运算的SIMD代码,c,optimization,simd,C,Optimization,Simd,我正在使用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 <

我正在使用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;  
    }  
}  
b=1;
对于(i=WPE-1;i>=0;--i){
ew=e[i];

for(j=0;jfor循环中的所有函数都应该是SIMD函数,而不仅仅是两个。为这两个函数设置参数所花费的时间比原始示例(很可能是由编译器优化的)要少。

用于32位int数据的SIMD循环通常如下所示:

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);
}
(i=0;i { //用数组索引i..i+3处的数据加载输入向量 __m128 va=毫米荷载128(&A[i]); __m128 vb=_mm_load_si128(&B[i]); //使用SIMD指令的过程向量(即无标量代码) __m128 vc=_mm_add_epi32(va,vb); //将结果向量存储在数组索引i..i+3处 _mm_store_si128(&C[i],vc); }
如果您发现需要在循环中的标量代码和SIMD代码之间切换,那么SIMD优化可能不会带来任何好处


SIMD编程的大部分技能来自于找到方法使算法在给定SIMD体系结构提供的有限数量的受支持指令和数据类型下工作。通常需要利用数据集的先验知识来获得最佳性能,例如,如果您确定您的32位整数值的范围实际上在16位以内,这将使算法的乘法部分更容易实现。

+1:在标量代码和SIMD代码之间移动是昂贵的-任何给定循环的SIMD优化都需要“全部或无”你的意思是我需要用SIMD对应项替换赋值、乘法、除法运算吗?我使用的是SSE2。我看到在上面的例子中,没有任何乘法函数可以一次计算4个32位数字的乘积。除法也是如此。那么应该怎么做呢?@anup我看到你在复制一些data从e1、e2、e3、e4阵列到EW.data阵列。这很糟糕。然后你正在对该数据执行一些操作。从SSE2函数中,你只是在使用shift。如果SSE2没有你需要的函数,那么你就不能使用它。或者你必须做一些smartWell,我是SIMD的新手,因此我对它和如何在中执行操作没有太多的知识你能解释一下为什么这些作业不好吗?
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);
}