C++ 在64位x 64位乘法中使用Karatsuba算法真的有效吗?

C++ 在64位x 64位乘法中使用Karatsuba算法真的有效吗?,c++,performance,parallel-processing,simd,avx2,C++,Performance,Parallel Processing,Simd,Avx2,我在AVX2上工作,需要计算64位x64位->128位加宽乘法,并以最快的方式获得64位高部分。由于AVX2没有这样的指令,我使用Karatsuba算法来提高效率和提高速度是否合理?不尝试就很难判断,但只使用AMD64 MUL指令可能会更快,AMD64 MUL指令支持64x64=128,吞吐量与大多数AVX2指令相同(但没有矢量化)。缺点是,如果操作数在YMM寄存器中,则需要加载到常规寄存器。这将为单个64x64=128提供类似于加载+多线程+存储的功能 如果可以用AVX2对Karatsuba进

我在AVX2上工作,需要计算64位x64位->128位加宽乘法,并以最快的方式获得64位高部分。由于AVX2没有这样的指令,我使用Karatsuba算法来提高效率和提高速度是否合理?

不尝试就很难判断,但只使用AMD64 MUL指令可能会更快,AMD64 MUL指令支持64x64=128,吞吐量与大多数AVX2指令相同(但没有矢量化)。缺点是,如果操作数在YMM寄存器中,则需要加载到常规寄存器。这将为单个64x64=128提供类似于加载+多线程+存储的功能

如果可以用AVX2对Karatsuba进行矢量化,请同时尝试AVX2和
MUL
,看看哪个更快。如果你不能矢量化,单
MUL
可能会更快。如果您可以删除加载并存储到常规寄存器,那么single
MUL
肯定会更快

MUL
和AVX2指令在内存中都可以有一个具有相同吞吐量的操作数,这可能有助于消除
MUL

的一个负载,它在一条指令中执行64bx64b到128b。我知道有一个例外

但是,如果你不需要精确的64 Bx64 B到128B,你可以考虑。 使用53bx53b至106b

将四个53位数字
a
b
相乘,得到四个106位数字,只需要两条指令:

__m256 p = _mm256_mul_pd(a,b);
__m256 e = _mm256_fmsub_pd(a,b,p);

这在两条指令中给出了四个106位数字,而在一条指令中使用了
mulx

否。在现代体系结构中,Karatsuba击败教科书乘法的交叉点通常在8到24个机器字之间(例如x86_64上的512到1536位)。对于固定大小,阈值位于该范围的较小端,新的ADCX/ADOX指令可能会使标量代码的阈值更高,但64x64仍然太小,无法从Karatsuba中获益。

这在很大程度上取决于体系结构。25年前,我在32位SPARC处理器上使用Karatsuba进行64x64->128位乘法运算,以获得一些增量性能增益。我还没有看过AVX2,因为我的机器中缺少Haswell类CPU。你有没有搜索过文献(或互联网),看看其他人发现了什么?使用标准方法,基于AVX2的64x64->128位乘法的速度有多快?您真的需要64bx64b到128b吗?或者你可以使用56bx56b到106b吗?实际上我需要64bx64b->64b高位,这样“我想你应该在你的问题中说明你想要64bx64b到高64b。如果你问我是否有一种使用AVX2的快速方法来实现
高(64bx64b)
,你的问题会更有趣。你的问题可以被认为是a,因为你真的想找到一种更快的方法来做
high(64bx64b)
。花费在零件上的时间最多:(((();那么你能对这个答案说些什么呢@user1979163是否启用了所有优化?使用GCC,整个功能仅转换为4条汇编指令(
mov
mov
mul
mov
)。这就是禁用内联的情况。这4条指令在CPU内部应该具有良好的并行吞吐量。我不确定你能做得更好。是的,我启用了所有优化并编译为g++-mavx2-O3-ftree vectorize-ftree vectorizer verbose=2 mulhiExample.cpp-std=c++11-fabi version=0。你能提供你编译的代码和你使用的标志吗?@user1979163我使用了你提供的代码,删除了静态内联。我用你的选项得到了相同的程序集,所以你可能得到了相同的结果。此函数是否仅在同一.cpp文件中使用?如果在其他地方使用,它将不会内联,即使使用
inline
。在这种情况下可能要花很多钱。要启用内联,请将函数定义放在.h中,或使用-flto编译。如果您仅在同一个.cpp文件中使用此函数,则可能是运气不佳。@user1979163请注意,如果您使用-flto,则还需要将-O3传递给链接器命令,否则它将毫无用处。这回答了OPs的问题,但我认为如果OP询问是否有办法击败
mulx
以获得
高性能,则更有趣(64bx64b)
使用AVX2(这就是我选择将OPs问题解释为xy问题的方式)。我认为在浮点域中使用双-双算法可能是可行的(假设OP可以在大多数算法中保持在浮点域)。如果提问者真的在做整数运算,并且乘法是所讨论代码的一个重要部分,那么就不可能打败MULX。如果任务本质上是整数,那么使用FMA很有趣,但会遇到两个痛点:(a)操作数和高积的舍入;(b)如果输入不总是全宽的,那么产品最终会有不同的指数,这使得后续操作变得非常痛苦。你可能是对的。我还没有尝试实现这一点。这是我一直在考虑的一个想法。从某种意义上说,舍入可能是一种前期成本,这就是我所说的保持浮动dom的意思ain对于大多数算法来说都是如此。不同的指数是一个问题。也许更大的问题是是否也需要加法。双倍加法速度慢,返回整数域进行加法是另一种开销,AVX2比较和加法将幸运地与ADCX实现收支平衡。根据我的经验,“有用的”在现代处理器上,Karatsuba的范围正在迅速缩小。像MULX和ADX这样的东西正在使basecase算法越来越快,从而推高basecase/Karatsuba阈值。另一方面,浮点FFT正充分利用SIMD,它正在蚕食Karatsuba/FFT阈值并将其推低。@Zboson:在32b流程中,这是一个非常复杂的问题