有256位整数类型吗?

Cac*_*ito 2 c gcc types x86-64

操作系统:Linux(Debian 10)

CC:GCC 8.3

CPU:i7-5775C

在GCC中有一个unsigned __int128/ __int128,但是有什么办法在GCC中有一个uint256_t/ int256_t

我读过一篇__m256i似乎来自英特尔的文章。我可以包含任何标头来获取它吗?

它像假设一样有用unsigned __int256吗?我的意思是,如果您可以为其分配/比较,比较,按位运算等。

它的等效符号是什么(如果有)?


编辑1:

我做到了:

#include <immintrin.h>
typedef __m256i uint256_t;
Run Code Online (Sandbox Code Playgroud)

并编译。如果可以进行一些操作,请在此处进行更新。


编辑2:

发现问题:

uint256_t   m;
ptrdiff_t   l = 5;

m = ~((uint256_t)1 << l);
Run Code Online (Sandbox Code Playgroud)

输出:

error: can’t convert a value of type ‘int’ to vector type ‘__vector(4) long long int’ which has different size
  m = ~((uint256_t)1 << l);
Run Code Online (Sandbox Code Playgroud)

Pet*_*des 6

不,在gcc或任何其他主流x86-64编译器中没有直接/内置的编译器支持256位整数。您需要一个使用随身携带(或模拟)的库1

__m256i是AVX2 SIMD 4x uint64_t(或像8x这样较窄的元素大小uint32_t)。 它不是256位标量整数类型,您不能将其用于标量运算,__m256i var = 1甚至不会编译。x86 SIMD不支持大于64位的整数,而Intel固有类型(例如__m128i和)__m256i仅用于SIMD。

海合会__int128/ unsigned __int128通常使用标量add/adc,及/或标mul/ imul,因为一般AVX2是扩展精度没有帮助。(仅适用于与元素边界无关的按位AND / OR / XOR之类的东西。)


脚注1:不幸的是C不提供运出从加法/减法,所以它甚至不是方便用C编写 sum = a+b/ carry = sum<a适用于随身携带出来的时候有一个在没有进位,但它更难用C编写和全加器编译器通常将废话汇编不仅在可用的机器上使用本机随身携带指令。很大的整数(例如GMP)的扩展精度库通常用asm编写。

  • @CacahueteFrito不,`__m256i`用于AVX2,它不是单个256位整数 (2认同)

Her*_*nSW 6

我只在 Pollard Rho 算法中计算“f(x) = (x^2+a) mod n”时才需要“uint256_t”。函数“f”之外的所有变量都是内置类型 __uint128_t。

我为此目的实现了 uint256_t ,如下所示:

typedef __uint128_t uint256_t[2];

Run Code Online (Sandbox Code Playgroud)

然后我实现了计算“f()”所需的函数:

__uint128_t set_128(unsigned long h, unsigned long l);
void set_256(uint256_t d, __uint128_t l, __uint128_t h);
void add_128(uint256_t d, uint256_t x, __uint128_t a);
void add_256(uint256_t d, uint256_t x, uint256_t a);
void shl_256(uint256_t d, long s);
void sqr_128(uint256_t d, __uint128_t x);
several print functions and macros for printing 128bit and 256bit numbers
__uint128_t mod_256(uint256_t x, __uint128_t n);
__uint128_t f(__uint128_t x);
Run Code Online (Sandbox Code Playgroud)

在此要点中找到实现:
https://gist.github.com/Hermann-SW/a20af17ee6666467fe0b5c573dae701d

我确实针对 gmplib 函数对我的代码进行了基准测试,并在所有方面都实现了比 gmplib 的加速(经过大量工作),有关详细信息:
https://www.raspberrypi.org/forums/viewtopic.php ?f=33&t=311893&p=1873552# p1873552

函数执行 100 万次的运行时间(以纳秒为单位):
在此输入图像描述

  • 对于显示普通“__uint128_t”155k 加速因子的基准测试,很可能大部分工作都被优化掉或被提升到循环之外,但 gmp 函数调用对优化器来说是不透明的。现代 Intel/AMD CPU 的循环速度不可能超过每个时钟周期 1 次迭代,或者每个时钟执行超过 1 个标量 64x64 =&gt; 128 位 `mul`。如果您发现您的代码运行速度比这更快,那么它实际上已经优化了。(4GHz 下的 147 ns 只有 588 个周期,如果没有巨大的算法优化,即不做所有的工作,做一百万件事是完全不可能的) (2认同)
  • 如果您不对其进行特殊处理,那么“易失性”可能会造成不必要的伤害,强制额外负载并阻止编译器注意到“a_high * a_low”与“a_low * a_high”是相同的计算相反,当内联两个参数相同的普通乘法函数时,依靠编译器来注意到冗余。或者只是在每次提到“a”时从所有额外负载中进行一般性的额外工作。微基准测试很困难:您必须检查汇编,看看循环中的工作是否正是您想要测量的。(尽管 DoNotOptimize 可以提供很大帮助。) (2认同)
  • @HermannSW 您能否用新发现的“合理”加速更新您的表格?使用 [table markdown](https://meta.stackexchange.com/questions/356997/new-feature-table-support) 也可能很有用。 (2认同)