C++ 求两个无符号整数c+乘积的高32位的有效方法+;

C++ 求两个无符号整数c+乘积的高32位的有效方法+;,c++,compiler-optimization,C++,Compiler Optimization,我试图找出获得两个无符号整数乘积的高32位的最有效方法。 例如,使用CUDA编程,我只需unsigned int first32位=uu umulhi(a,b)并获得高32位 有没有办法在C++中做这种事情?p> 以下是我的方法: unsigned int a = 4294967295; // (2^32)-1 unsigned int b = 2; 有什么方法可以让我的方法更快吗?像u umulhi()这样的内部函数被设计为在特定的体系结构(这里是Nvidia GPU)上使用更少的/专门

我试图找出获得两个无符号整数乘积的高32位的最有效方法。 例如,使用CUDA编程,我只需
unsigned int first32位=uu umulhi(a,b)
并获得高32位

有没有办法在C++中做这种事情?p> 以下是我的方法:

unsigned int a = 4294967295;  // (2^32)-1
unsigned int b = 2; 
有什么方法可以让我的方法更快吗?

像u umulhi()这样的内部函数被设计为在特定的体系结构(这里是Nvidia GPU)上使用更少的/专门的指令。您必须查看注释(如CPU)中建议的专有解决方案,而不是期望C++中的某些东西。
在这种情况下,我非常怀疑您是否会找到一种内在的方法,用任何有意义的性能提高来取代您的方法。

除非有一些依赖于体系结构的电路将imulh32映射到本机指令,否则我认为这是您能做的最好的方法

查看由
g++6.3
为您的函数生成的程序集,很明显,由于
shr$0x20
的原因,
1
程序集操作的成本比只执行乘法的函数要高

unsigned long c = ( ((unsigned long)a * (unsigned long)b ) >> 32) & 0x00000000FFFFFFFF;
unsigned long umulhi32(unsigned int x,unsigned int y)
{
返回(((无符号长)a*(无符号长)b)>>32);
}
0000000000000960 :
960:89 f8 mov%edi,%eax
962:89 f7移动%esi,%edi
964:48 0f af c7 imul%rdi,%rax
968:48 c1 e8 20 shr$0x20,%rax
96c:c3 retq
96d:0f 1f 00 nopl(%rax)
cuda umulhi
的程序集用于查看它是否映射到某个专用的PTX指令,我认为很可能是这样的,因为
cuda
使用的
PTX
程序集公开了例如
mul24
其中()

mul24.hi执行24x24位乘法运算,并返回数据的高32位 48位结果

据我所知,x86汇编中没有这样的指令


希望这有帮助。

我不认为标准C++给你提供了高效的工具。您需要查看专有方法,例如您为CUDA发现的“最有效”方法。。并且没有提供任何关于平台的信息。编写正确的代码,如果速度不够快,无法看到实际的瓶颈所在,则对其进行分析。如果您的平台上没有等效的umulhi(),则可能需要编写一些汇编代码。优化编译器可能会生成与umulhi()等价的最佳代码。@Mint.K“最有效”的方法在很大程度上取决于底层架构。发布代码并不会让你的问题更容易回答。例如,如果int是32位,那么您已经有了高32位。和低32位。但是您没有告诉我们您在哪个平台上。解决方案是不可移植的,因为无符号长可能是32位。x86中没有这样的指令,因为单操作数
mul
imul
总是产生完整的结果。然而,SSE/AVX通常具有非加宽乘法,因此存在诸如PMULHUW、PMULHW、PMULHRSW等指令。。。为了得到高水平的结果,我不是一个真正的低水平的人!所以这绝对是一个有趣的补充。谢谢
 unsigned long umulhi32( unsigned int x,  unsigned int y)
{
  return ( ((unsigned long)a * (unsigned long)b ) >> 32);
}
0000000000000960 <_Z8umulhi32jy>:
 960:   89 f8                   mov    %edi,%eax
 962:   89 f7                   mov    %esi,%edi
 964:   48 0f af c7             imul   %rdi,%rax
 968:   48 c1 e8 20             shr    $0x20,%rax
 96c:   c3                      retq   
 96d:   0f 1f 00                nopl   (%rax)