查找用于提升多精度 uint512_t 的 First Set 指令 (ffs)
Posted
技术标签:
【中文标题】查找用于提升多精度 uint512_t 的 First Set 指令 (ffs)【英文标题】:Find First Set instruction (ffs) for boost multiprecision uint512_t 【发布时间】:2019-10-02 18:36:40 【问题描述】:我正在开发一种使用__builtin_ffsll()
和uint64_t
类型的算法。
我想使用 boost 多精度库切换到 512 位字段(我在支持 avx512 的机器上运行)。
有没有和上面提到的内置函数类似的功能?或者,我怎样才能有效地为 512 位整数实现这样的功能?
【问题讨论】:
【参考方案1】:来自the documentation:
unsigned lsb(const number-or-expression-template-type& x);
返回设置为 1 的最低有效位的(从零开始的)索引。
如果参数是
<= 0
,则抛出std::range_error
。
ffs()
是从 1 开始的,所以将 1 加到 lsb()
的返回值将使其等价。编辑:正如所指出的,考虑到传递 0 的情况。
可能是这样的
unsigned ffs512(const boost::multiprecision::uint512_t &n)
if (n.is_zero())
return 0;
else
return boost::multiprecision::lsb(n) + 1;
【讨论】:
还要注意输入 == 0 的不同行为。似乎lsb
旨在包装诸如 x86 的 bsf
指令之类的东西,该指令仅在输入为零时设置一个标志;它不会将有用的值写入输出寄存器。但是ffs
确实处理了 input==0 的情况,返回了0
。
512 位整数上的 lsb
是否实际编译为使用 vptestmd
/ vpcompressd
或类似方法的 AVX512 序列来查找第一个非零 dword,然后使用 vmovd
提取它到tzcnt
的整数寄存器? (或使用 2x 256 位向量来避免将 CPU 置于 512 位 SIMD 模式。)OP 希望这在 x86 上高效,可能是使用 gcc 和/或使用-O3 -march=skylake-avx512
@PeterCordes 我想 GMP 后端调用 mpz_scan1()
。对其他人一无所知。
@PeterCordes 我认为 GMP 只有通用版本的 mp[nz]_scan1 因为与乘法或更差的除法和 gcd 相比,它从来都不是限制因素。如果您认为它很有用,并且您可以为大型扫描提供更快的版本,并且不会显着减慢扫描几乎立即找到 1 位的常见情况,您可以尝试将其贡献给 GMP。但实际上 OP 有一个更简单的情况来处理,总是从头开始扫描。而当前的lsb
对他们来说可能已经足够快了。
看起来这个uint512_t
只为cpp_int
后端定义了类型,所以对于这个问题,gmp 后端如何实现它并不重要。以上是关于查找用于提升多精度 uint512_t 的 First Set 指令 (ffs)的主要内容,如果未能解决你的问题,请参考以下文章
如何以二进制形式显示 C++ Boost Library 多精度大整数?