我有一个使用GCC __uint128_t
的C程序很棒,但现在我的需求已经超越了它。
对于196或256位的快速算术,我有哪些选择?
我需要的唯一操作是加法(我不需要进位,即,我将使用mod 2 ^ 192或2 ^ 256)。
速度很重要,所以如果可能的话,我不想转向一般的多精度。 (实际上我的代码确实在某些地方使用了多精度,但这是在关键循环中并且将运行数百亿次。到目前为止,多精度需要运行数万次。)
也许这很简单,可以直接编码,或者我需要找一些合适的库。
你的建议是什么,哦,Stack Overflow?
澄清:GMP对我的需求来说太慢了。虽然我实际上在我的代码中使用了multiprecision,但它不在内循环中并且运行时间少于10 ^ 5次。热循环运行更像10 ^ 12次。当我改变我的代码(增加一个尺寸参数)以使多精度部分比单精度运行更频繁时,我的速度减慢了100倍(主要是由于内存管理问题,我认为,而不是额外的μops)。我希望将其降低到4倍或更好。
答案 0 :(得分:4)
256位版本
__uint128_t a[2], b[2], c[2]; // c = a + b
c[0] = a[0] + b[0];
c[1] = a[1] + b[1] + (c[0] < a[0]);
如果你在循环中多次使用它,你应该考虑通过SIMD和多线程使其并行
编辑:192位版本。通过这种方式,您可以消除128位比较,就像@ harold所说的那样:
struct __uint192_t {
__uint128_t H;
__uint64_t L;
} a, b, c; // c = a + b
c.L = a.L + b.L;
c.H = a.H + b.H + (c.L < a.L);
答案 1 :(得分:2)
您可以测试来自this answer的“添加(low < oldlow)
来模拟进位”技术是否足够快。这里low
是__uint128_t
这可能会影响代码生成,这有点复杂。您也可以尝试使用4 uint64_t
,我不知道这是好还是坏。
如果这还不够好,请放入内联汇编,并直接使用进位标志 - 它没有比这更好,但是你有使用内联汇编的常见缺点。