2

GMP/MPIR multiplicaiton 中的主要代码片段是 mpn_mul_basecase:

mp_limb_t addmul_1(mp_ptr rp, mp_srcptr up, mp_size_t n, mp_limb_t vl)
{
    mp_limb_t ul, cl, hpl, lpl, rl;
    cl = 0;
    do
    {
        ul = *up++;
        umul_ppmm(hpl, lpl, ul, vl);
        lpl += cl;
        cl = (lpl < cl) + hpl;
        rl = *rp;
        lpl = rl + lpl;
        cl += lpl < rl;
        *rp++ = lpl;
    } while (--n != 0);
    return cl;
}

VC++ 在哪里

#    define umul_ppmm(xh, xl, m0, m1)       \
     do  {                                  \
           xl = _umul128( (m0), (m1), &xh); \
         } while (0) 

对于 128 位类型的 GCC:

         do  {                                  \
        mp_limb_double_t w = (mp_limb_double_t)x * y; \
        r_lo = (mp_limb_t)w;                             \
        r_hi = (mp_limb_t)(w >> GMP_LIMB_BITS);                     \
    } while (0) 

但是指定处理器(我的处理器是 Haswell)的优化 asm 代码要快两倍:https ://github.com/wbhart/mpir/blob/master/mpn/x86_64w/haswell/addmul_1.asm 为什么?因为这个循环被扩展或者使用mulx而不是mul?我注意到源内存必须由 RSI 有效索引,而目标内存必须由 RDI 有效索引。但我不知道必须读取+添加+写入的索引存储单元的效率如何。可以用普通的C对其进行优化吗?我看到的是 _addcarry_u64 ,但也很慢。

4

0 回答 0