相关疑难解决方法(0)

Rust的128位整数“ i128”如何在64位系统上工作?

Rust具有128位整数,这些整数用数据类型表示i128u128对于无符号整数):

let a: i128 = 170141183460469231731687303715884105727;
Run Code Online (Sandbox Code Playgroud)

Rust如何使这些i128值在64位系统上工作?例如,如何对这些进行算术运算?

据我所知,既然该值不能容纳在x86-64 CPU的一个寄存器中,那么编译器是否会以某种方式使用2个寄存器i128?还是他们改用某种大整数结构来表示它们?

x86-64 int128 bigint rust llvm-codegen

116
推荐指数
4
解决办法
1万
查看次数

Why does Windows64 use a different calling convention from all other OSes on x86-64?

AMD has an ABI specification that describes the calling convention to use on x86-64. All OSes follow it, except for Windows which has it's own x86-64 calling convention. Why?

Does anyone know the technical, historical, or political reasons for this difference, or is it purely a matter of NIHsyndrome?

I understand that different OSes may have different needs for higher level things, but that doesn't explain why for example the register parameter passing order on Windows is rcx - rdx …

windows x86-64 calling-convention

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

gcc中有128位整数吗?

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

c gcc x86-64 bigint 128-bit

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

长整数例程可以从SSE中受益吗?

我还在研究C++中任意长整数的例程.到目前为止,我已经为64位Intel CPU实现了加/减和乘法.

一切正常,但我想知道我是否可以通过使用SSE来加快速度.我浏览了SSE文档和处理器指令列表,但我找不到任何我认为可以使用的内容,原因如下:

  • SSE有一些整数指令,但大多数指令处理浮点.看起来它不是设计用于整数(例如,是否有较小的整数比较?)

  • SSE的想法是SIMD(相同的指令,多个数据),因此它提供了2或4个独立操作的指令.另一方面,我希望有一个像128位整数加(128位输入和输出)的东西.这似乎不存在.(但是?在AVX2中可能?)

  • 整数加法和减法既不处理输入也不处理输出.因此,手动操作非常麻烦(因而也很慢).

我的问题是:我的评估是正确的还是有什么我忽略的?长整数例程可以从SSE中受益吗?特别是,它们可以帮助我编写更快的添加,子或mul例程吗?

performance integer sse bignum arbitrary-precision

19
推荐指数
1
解决办法
3773
查看次数

我可以使用AVX FMA单元进行精确的52位整数乘法吗?

AXV2没有任何整数乘法,其源大于32位.它提供32 x 32 - > 32乘法,以及32 x 32 - > 64乘以1,但没有64位源.

假设我需要一个输入大于32位但小于或等于52位的无符号乘法 - 我可以简单地使用浮点DP乘法或FMA指令,并且当整数输入和输出时输出将是位精确的结果可以用52或更少的比特表示(即,在[0,2 ^ 52-1]范围内)?

如果我想要产品的所有104位更一般的情况怎么样?或整数乘积超过52位的情况(即,产品在位索引中的非零值> 52) - 但我只想要低52位?在后一种情况下,它MUL会给我更高的位并舍去一些低位(也许这就是IFMA帮助的?).

编辑:事实上,根据这个答案,也许它可以做任何高达2 ^ 53的事情- 我忘记了1在尾数之前隐含的领先有效地给了你一点.


1有趣的是,正如Mysticial 在评论中所解释的那样,64位产品PMULDQ操作的延迟是32位PMULLD版本的一半,吞吐量是32位版本的两倍.

floating-point x86 simd avx2 fma

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

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

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

assembly sse sse2

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

实用的BigNum AVX/SSE可能吗?

SSE/AVX寄存器可以被视为整数或浮点BigNums.也就是说,人们可以忽视存在通道.是否有一种简单的方法可以利用这种观点并将这些寄存器单独或组合用作BigNum?我问,因为我从BigNum库中看到的很少,它们几乎普遍存储并对数组进行算术运算,而不是SSE/AVX寄存器.可移植性?

例:

假设您将SSE寄存器的内容存储为a中的键std::set,您可以将这些内容作为BigNum进行比较.

sse simd biginteger avx extended-precision

10
推荐指数
2
解决办法
3167
查看次数

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
查看次数

SIMD使用无符号乘法对64位*64位到128位进行签名

我创建了一个使用SIMD进行64位*64位到128位的功能.目前我已经使用SSE2(acutally SSE4.1)实现了它.这意味着它可以同时运行两个64b*64b到128b的产品.同样的想法可以扩展到AVX2或AVX512,同时提供四个或八个64b*64到128b的产品.我的算法基于http://www.hackersdelight.org/hdcodetxt/muldws.c.txt

该算法进行一次无符号乘法,一次有符号乘法和两次有符号*无符号乘法.签名的*signed和unsigned*unsigned操作很容易使用_mm_mul_epi32_mm_mul_epu32.但混合签名和未签名的产品给我带来了麻烦.例如,考虑一下.

int32_t x = 0x80000000;
uint32_t y = 0x7fffffff;
int64_t z = (int64_t)x*y;
Run Code Online (Sandbox Code Playgroud)

双字产品应该是0xc000000080000000.但是如果你假设你的编译器知道如何处理混合类型,你怎么能得到这个呢?这就是我想出的:

int64_t sign = x<0; sign*=-1;        //get the sign and make it all ones
uint32_t t = abs(x);                 //if x<0 take two's complement again
uint64_t prod = (uint64_t)t*y;       //unsigned product
int64_t z = (prod ^ sign) - sign;    //take two's complement based on the sign
Run Code Online (Sandbox Code Playgroud)

使用SSE可以这样做

__m128i xh;    //(xl2, xh2, xl1, xh1) high is signed, low unsigned
__m128i …
Run Code Online (Sandbox Code Playgroud)

c x86 integer sse bit-manipulation

9
推荐指数
2
解决办法
4203
查看次数

如何将两个SSE寄存器加在一起

我有两个SSE寄存器(128位是一个寄存器),我想把它们加起来.我知道如何在其中添加相应的单词,例如,_mm_add_epi16如果我在寄存器中使用16位字,我可以这样做,但我想要的是_mm_add_epi128(不存在),它将使用寄存器作为一个大字.有没有办法执行此操作,即使需要多个指令?
我正在考虑使用_mm_add_epi64,检测正确字中的溢出,然后在需要时在寄存器中向左侧字添加1,但我也希望这种方法适用于256位寄存器(AVX2),这种方法似乎太复杂了.

c c++ sse intel avx2

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

256位定点算术,未来?

只是一些愚蠢的想法,但如果计算机能够有效地计算256位算术,比如他们有256位架构,我想我们可以取消浮点.我也想知道,如果有任何理由要超越256位架构?我的基础是相当脆弱的,但我相信如果我错了你就会把我直截了当;)这是我的想法:

您可以使用256位类型,使用127或128位作为整数,使用127或128位作为小数值,然后使用符号位.如果您的硬件能够计算,存储和移动这些大数字而没有任何问题,我认为您将设置为处理您遇到的任何计算.

一个例子:如果您使用长度,并且您以米为单位表示所有值,则最小值(2 ^ -128米)将小于普朗克长度,最大值(2 ^ 127米)将更大比可观察宇宙的直径.想象一下,计算精度小于普朗克长度的光年数?

好吧,这只是一个例子,但我很难想到任何可能保证数量大于小的情况.有什么想法吗?我没有考虑定点运算是否存在问题?创建256位架构是否存在问题?

floating-point precision performance fixed-point cpu-architecture

4
推荐指数
1
解决办法
754
查看次数