我写了一个小整数算术的小库。我的减法算法中有一个跟随循环:
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;
}
这个循环正常,但我发现它不是那么有效。帮助我优化这个循环(也许,使用特殊技巧或汇编插入)。
答案 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++;
}
}
如果您正在考虑装配,那么大多数处理器都会使用借位指令进行减法,从而无需手动检查借位。