相关疑难解决方法(0)

使用进位标志进行高效的128位加法

我在我的C++代码的内部循环中使用了128位整数计数器.(不相关背景:实际应用是评估规则网格上的有限差分方程,其中涉及重复递增大整数,甚至64位也不够精确,因为小的舍入累积足以影响答案.)

我将整数表示为两个64位无符号长整数.我现在需要将这些值递增128位常数.这并不难,但你必须手动捕捉低字到高字的进位.

我有这样的工作代码:

inline void increment128(unsigned long &hiWord, unsigned long &loWord)
  {
    const unsigned long hiAdd=0x0000062DE49B5241;
    const unsigned long loAdd=0x85DC198BCDD714BA;

    loWord += loAdd;
    if (loWord < loAdd) ++hiWord; // test_and_add_carry
    hiWord += hiAdd;
  }
Run Code Online (Sandbox Code Playgroud)

这是一个紧凑而简单的代码.有用.

不幸的是,这大约是我运行时的20%.这条杀手线就是低价测试.如果我删除它,我显然得到了错误的答案,但运行时开销从20%下降到4%!因此携带测试特别昂贵!

我的问题:C++是否公开了硬件进位标志,即使是作为GCC的扩展?如果实际编译的指令使用最后一个进位指令进行添加,似乎可以在没有上面的测试和添加进位线的情况下完成添加.有没有办法重写test-and-add-carry行以使编译器使用内部操作码?

c++ assembly gcc bigint carryflag

39
推荐指数
2
解决办法
8350
查看次数

gcc中有128位整数吗?

我想要一个128位整数,因为我想存储两个64位数的乘法结果.在gcc 4.4及以上版本中有没有这样的东西?

c gcc x86-64 bigint 128-bit

39
推荐指数
3
解决办法
6万
查看次数

使用clang的携带代码生成良好的添加

我正在尝试生成代码(目前使用clang ++ - 3.8),它添加了两个由多个机器字组成的数字.为了简化目前我只添加128位数字,但我希望能够概括这一点.

首先是一些typedef:

typedef unsigned long long unsigned_word;
typedef __uint128_t unsigned_128;
Run Code Online (Sandbox Code Playgroud)

而"结果"类型:

struct Result
{
  unsigned_word lo;
  unsigned_word hi;
};
Run Code Online (Sandbox Code Playgroud)

第一个函数f采用两对无符号字并返回结果,作为一个中间步骤,在添加它们之前将这两个64位字放入一个128位字中,如下所示:

Result f (unsigned_word lo1, unsigned_word hi1, unsigned_word lo2, unsigned_word hi2)
{
  Result x;
  unsigned_128 n1 = lo1 + (static_cast<unsigned_128>(hi1) << 64);
  unsigned_128 n2 = lo2 + (static_cast<unsigned_128>(hi2) << 64);
  unsigned_128 r1 = n1 + n2;
  x.lo = r1 & ((static_cast<unsigned_128>(1) << 64) - 1);
  x.hi = r1 >> 64;
  return x;
}
Run Code Online (Sandbox Code Playgroud)

这实际上非常好地内联:

movq    8(%rsp), …
Run Code Online (Sandbox Code Playgroud)

c++ optimization assembly clang adx

26
推荐指数
1
解决办法
1206
查看次数

如果我的编译器不支持它们,如何在C或C++中添加和减去128位整数?

我正在为128位数字的长流写一个压缩器.我想将数字存储为差异 - 仅存储数字之间的差异而不是数字本身,因为我可以将差异打包在更少的字节中,因为它们更小.

但是,对于压缩,我需要减去这些128位值,对于解压缩,我需要添加这些值.我的编译器的最大整数大小是64位宽.

任何人有任何想法有效地做到这一点?

c++ integer 128-bit

23
推荐指数
4
解决办法
3万
查看次数

最快的128位整数库

我正在研究CPU繁重的数值计算应用程序.没有进入很多细节,它是一个计算数学研究项目,涉及为大整数x计算某个函数f(x).

现在,所有内容都是在x64模式下使用C++实现的,使用本机64位整数.这限制了我x <2 ^ 64~1.8*10 ^ 19.我想更进一步,为此,我需要一个执行128位算术的库.它必须非常快.特别是,整数除法应该很快.否则我会坐在这里等待结果直到感恩节.而且我宁愿不重新发明轮子.

我在维基百科上找到了一个大约20个大整数库的列表,但其中大多数似乎都是针对任意精度的数字,这对我的任务来说太过分了,我不需要额外的费用.

有谁知道哪个库可以最快地运行128位整数?

c c++ numerical biginteger

14
推荐指数
2
解决办法
1万
查看次数

cuda上的128位整数?

我刚刚设法在Linux Ubuntu 10.04下安装我的cuda SDK.我的显卡是NVIDIA geForce GT 425M,我想用它来解决一些繁重的计算问题.我想知道的是:有没有办法使用一些无符号的128位int var?当使用gcc在CPU上运行我的程序时,我使用的是__uint128_t类型,但是将它与cuda一起使用似乎不起作用.在cuda上有128位整数可以做些什么吗?

非常感谢Matteo Monti Msoft编程

integer cuda nvidia 128-bit

13
推荐指数
2
解决办法
1万
查看次数

使用进位标志添加多字

GCC具有128位整数.使用这些我可以让编译器使用mul(或imul只有一个操作数)指令.例如

uint64_t x,y;
unsigned __int128 z = (unsigned __int128)x*y;
Run Code Online (Sandbox Code Playgroud)

生产mul.我用它来创建一个128x128到256的函数(在更新之前,请参阅此问题的结尾,如果您感兴趣,请参阅此代码).

现在我想要进行256位加法,ADC除了使用汇编之外,我还没有找到让编译器使用的方法.我可以使用汇编程序,但我想要内联函数以提高效率.编译器已经生成了一个有效的128x128到256函数(因为我在这个问题的开头解释了)所以我不明白为什么我应该在汇编中重写它(或者编译器已经有效实现的任何其他函数) .

这是我提出的内联汇编函数:

#define ADD256(X1, X2, X3, X4, Y1, Y2, Y3, Y4) \
 __asm__ __volatile__ ( \
 "addq %[v1], %[u1] \n" \
 "adcq %[v2], %[u2] \n" \
 "adcq %[v3], %[u3] \n" \
 "adcq %[v4], %[u4] \n" \
 : [u1] "+&r" (X1), [u2] "+&r" (X2), [u3] "+&r" (X3), [u4] "+&r" (X4) \
 : [v1]  "r" (Y1), [v2]  "r" (Y2), [v3]  "r" (Y3), [v4] …
Run Code Online (Sandbox Code Playgroud)

c x86 assembly gcc visual-c++

13
推荐指数
1
解决办法
2124
查看次数

是否可以使用SSE和SSE2来生成128位宽的整数?

我想更多地了解SSE2的功能,并想知道是否可以制作支持加法,减法,XOR和乘法的128位宽整数?

assembly sse sse2

10
推荐指数
1
解决办法
1417
查看次数

x86上的两个128位整数的高效乘法/除法(无64位)

编译器: MinGW/GCC
问题:不允许使用GPL/LGPL代码(GMP或任何bignum库,对于这个问题来说太过分了,因为我已经实现了这个类).

我构建了自己的128位固定大小的整数类(用于游戏引擎,但可以推广到任何用例),我发现当前乘法和除法运算的性能非常糟糕(是的,我有时间,见下文),我想改进(或改变)执行低级数字运算的算法.


当涉及乘法和除法运算符时,与几乎所有其他类似的运算符相比,它们是无法忍受的.

这些是相对于我自己的计算机的近似测量:

Raw times as defined by QueryPerformanceFrequency:
1/60sec          31080833u
Addition:              ~8u
Subtraction:           ~8u
Multiplication:      ~546u
Division:           ~4760u (with maximum bit count)
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,只是进行乘法比加或减慢很多倍.除法比乘法慢10倍.

我想提高这两个运算符的速度,因为每帧可能会进行非常多的计算(点积,各种碰撞检测方法等).


结构(方法省略)看起来有点像:

class uint128_t
{
    public:
        unsigned long int dw3, dw2, dw1, dw0;
  //...
}
Run Code Online (Sandbox Code Playgroud)

乘法目前使用典型的长乘法方法(在汇编中使我可以捕获EDX输出)同时忽略超出范围的单词(也就是说,mull与16相比,我只做10次).

除法使用移位 - 减法算法(速度取决于操作数的位数).但是,它不是在装配中完成的.我发现有点太难以集合并决定让编译器优化它.


我已经谷歌了几天看着描述算法的页面,例如Karatsuba乘法,高基数除法和牛顿拉普森分部,但数学符号有点太过分了.我想使用其中一些高级方法来加速我的代码,但我必须首先将"希腊语"翻译成可理解的东西.

对于那些可能认为我的努力"过早优化"的人; 我认为这个代码是一个瓶颈,因为非常基本的数学运算本身变得很慢.我可以在更高级别的代码上忽略这种类型的优化,但是这个代码将被调用/使用到足够重要.

我想建议我应该使用哪种算法来改进乘法和除法(如果可能的话),以及关于建议算法如何工作的基本(希望易于理解)解释将受到高度赞赏.


编辑:乘以改进

我能够通过将代码内联到operator*=来改进乘法运算,并且它似乎尽可能快.

Updated raw times:
1/60sec          31080833u
Addition:              ~8u
Subtraction: …
Run Code Online (Sandbox Code Playgroud)

c++ algorithm x86 bignum

9
推荐指数
1
解决办法
8552
查看次数

使用汇编语言进行128位移位?

在现代英特尔CPU(核心i7,沙桥)上进行128位移位的最有效方法是什么?

类似的代码在我最内层的循环中:

u128 a[N];
void xor() {
  for (int i = 0; i < N; ++i) {
    a[i] = a[i] ^ (a[i] >> 1) ^ (a[i] >> 2);
  }
}
Run Code Online (Sandbox Code Playgroud)

数据a[N]几乎是随机的.

performance x86 assembly 128-bit

8
推荐指数
1
解决办法
2866
查看次数

如何在汇编中乘以两个十六进制128位数

我在内存中有两个128位的十六进制数字,例如(小端):

x:0x12 0x45 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
y:0x36 0xa1 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
Run Code Online (Sandbox Code Playgroud)

我要执行这两个数字之间的无符号乘法,所以我的新数字将是:

z:0xcc 0xe3 0x7e 0x2b 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
Run Code Online (Sandbox Code Playgroud)

现在,我知道我可以将半个x和y数字移入raxrbx注册,例如,执行mul操作,并对另一半执行相同的操作.问题是,通过这样做,我失去了结转,我不知道如何避免这种情况.大约4个小时我面临这个问题,我能看到的唯一解决方案是二进制转换(and< - > shl,1).

你能给我一些关于这个问题的意见吗?
我认为最好的解决方案是占用一个字节的时间.

algorithm assembly byte x86-64 multiplication

5
推荐指数
2
解决办法
1507
查看次数

对128位数字进行按位移位操作

可以说我有一个由4个32位整数组成的数组,用于存储128位数字

如何在此128位数字上左右移动?

谢谢!

c c++ bit-manipulation bit-shift bitwise-operators

4
推荐指数
2
解决办法
6786
查看次数