在C ++中优化大整数减法

时间:2017-02-26 22:00:29

标签: c++ c assembly optimization

我写了一个小整数算术的小库。我的减法算法中有一个跟随循环:

unsigned * a, * ae, * b, * be; // pointers to array of big ints
unsigned long long C_MAX_DIG_1 = 1Ui64 << 32;
......
long long carry = 0;
for (;a != ae && b != be; ++a, ++b) {
    long long r = carry + *a - *b;
    r < 0 ? (r += C_MAX_DIG_1, carry = -1) : (carry = 0);
    *a = (unsigned)r;
}

这个循环正常,但我发现它不是那么有效。帮助我优化这个循环(也许,使用特殊技巧或汇编插入)。

2 个答案:

答案 0 :(得分:1)

而不是

for (;a != ae && b != be; ++a, ++b)

ptrdiff_t da = ae - a, db = be - b;
unsigned* ae2 = a + (da < db ? da : db);
for (;a != ae2; ++a, ++b)

这样,您将保存一个比较。如果循环很长,也许会让事情变得更快。

另外,找到最好的编译标志。也许你可以从匹配你的特定CPU的标志中受益(即-msse3用于GCC)。

此外,如果您拥有并准备使用多个处理器,您可能希望实现并行性。

我怀疑你能不能创造奇迹,因为大部分时间花在从RAM读取值并将其写回(假设它们在RAM而不是缓存中)。 RAM比CPU慢。

答案 1 :(得分:1)

这应该有效并且速度更快。我假设大整数的第一个单词是最不重要的单词,基于问题的代码。

// assumes size of a >= size of b
void subvv(unsigned *a, unsigned *ae, unsigned *b, unsigned *be)
{
unsigned r;                     // result
unsigned c = 0;                 // borrow
    while(b != be){
        r = *a - *b - c;
        // assuming compiler uses register for *a
        c = (r > *a)? 1 : 0;
        *a = r;
        a++;
        b++;
    }
    while(c && a != ae){
        r = *a - c;
        c = (r > *a)? 1 : 0;
        *a = r;
        a++;
    }
}

如果您正在考虑装配,那么大多数处理器都会使用借位指令进行减法,从而无需手动检查借位。