3
int u1, u2;  
unsigned long elm1[20], _mulpre[16][20], res1[40], res2[40]; 64 bits long     
res1, res2 initialized to zero.  

l = 60;  
while (l)  
{  
    for (i = 0; i < 20; i += 2)  
    {  
        u1 = (elm1[i] >> l) & 15;  
        u2 = (elm1[i + 1] >> l) & 15;

        for (k = 0; k < 20; k += 2)  
        {  
            simda = _mm_load_si128 ((__m128i *) &_mulpre[u1][k]);  
            simdb = _mm_load_si128 ((__m128i *) &res1[i + k]);  
            simdb = _mm_xor_si128  (simda, simdb);  
            _mm_store_si128 ((__m128i *)&res1[i + k], simdb);  

            simda = _mm_load_si128 ((__m128i *)&_mulpre[u2][k]);  
            simdb = _mm_load_si128 ((__m128i *)&res2[i + k]);  
            simdb = _mm_xor_si128  (simda, simdb);  
            _mm_store_si128 ((__m128i *)&res2[i + k], simdb);  
        } 
    }
    l -= 4;
    All res1, res2 values are left shifted by 4 bits.  
}

上面提到的代码在我的程序中被多次调用(profiler 显示 98%)。

编辑:在内部循环中, res1[i + k] 值会为相同的 (i + k) 值加载多次。我在 while 循环中尝试了这个,我将所有 res1 值加载到 simd 寄存器(数组)中,并在最里面的 for 循环中使用数组元素来更新数组元素。完成两个 for 循环后,我将数组值存储回 res1、re2。但是计算时间随之增加。知道我哪里错了吗?这个想法似乎是正确的

欢迎任何使它更快的建议。

4

4 回答 4

2

不幸的是,编译器可能已经完成了最明显的优化:

  • 你可以拉&_mulpre[u1]&mulpre[u2]我们的内循环。
  • 你可以拉&res1[i]我们的内循环。
  • 对两个内部操作使用不同的变量,并对它们重新排序,可能会实现更好的流水线操作。

可能交换外部循环将改善elm1.

于 2010-12-15T14:15:23.060 回答
0

对于这样的例程,您几乎无能为力,因为加载和存储将是主要因素(对于单个计算指令,您正在执行 2 个加载 + 1 个存储 = 4 个总线周期)。

于 2010-12-15T14:33:08.963 回答
0
l = 60;  
while (l)  
{  
    for (i = 0; i < 20; i += 2)  
    {  
        u1 = (elm1[i] >> l) & 15;  
        u2 = (elm1[i + 1] >> l) & 15;

        for (k = 0; k < 20; k += 2)  
        {  
            _mm_stream_si128 ((__m128i *)&res1[i + k],
                    _mm_xor_si128  (
                                    _mm_load_si128 ((__m128i *) &_mulpre[u1][k]),
                                    _mm_load_si128 ((__m128i *) &res1[i + k]
                                   ));  

            mm_stream_si128 ((__m128i *)&res2[i + k],    
                    _mm_xor_si128  (
                                    _mm_load_si128 ((__m128i *)&_mulpre[u2][k]), 
                                    _mm_load_si128 ((__m128i *)&res2[i + k])
                                   ));  
        } 
    }
    l -= 4;
    All res1, res2 values are left shifted by 4 bits.  
}
  1. 请记住您使用的是内在的,使用较少的_128mi/ _mm128 值将加快您的程序。
  2. 试试 _mm_stream_si128(),它可能会加快存储过程。
  3. 尝试预取
于 2010-12-23T14:19:53.040 回答
0

好吧,你总是可以少打电话:-)

总输入和输出数据看起来相对较小,具体取决于您的设计和预期输入,仅缓存计算或进行惰性评估而不是预先计算可能是可行的。

于 2010-12-15T14:31:08.230 回答