首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >32位整数乘法高阶位的高效计算

32位整数乘法高阶位的高效计算
EN

Stack Overflow用户
提问于 2009-09-08 23:54:36
回答 3查看 3.1K关注 0票数 10

许多CPU具有单个汇编操作码,用于返回32位整数乘法的高阶位。通常,将两个32位整数相乘会产生64位结果,但如果将其存储在32位整数中,则会将其截断为低32位。

例如,在PowerPC上,毛尔操作码返回一个时钟中32x32位乘法的64位结果的高32位。这正是我要找的,但更轻便。在NVidia数据自动化系统中也有类似的操作码umulhi()。

在C/C++中,是否有一种有效的方法来返回32x32乘法的高阶位?目前,我通过将其转换为64位来计算它,如下所示:

代码语言:javascript
复制
unsigned int umulhi32(unsigned int x, unsigned int y)
{
  unsigned long long xx=x;
  xx*=y;
  return (unsigned int)(xx>>32);
}

但这比常规的32乘32乘法慢11倍以上,因为我使用的是64位的数学运算,即使是乘法也是如此。

有更快的方法来计算高阶位吗?

这显然是,而不是--最好用BigInteger库来解决(这会造成巨大的开销)。

SSE似乎有PMULHUW,16x16 ->顶级16位版本,但没有像我想要的32x32 ->顶级32版本。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2009-09-09 00:17:36

gcc 4.3.2,使用-O1优化或更高版本,将您的函数转换为您向IA32程序集展示的功能,如下所示:

代码语言:javascript
复制
umulhi32:
        pushl   %ebp
        movl    %esp, %ebp
        movl    12(%ebp), %eax
        mull    8(%ebp)
        movl    %edx, %eax
        popl    %ebp
        ret

它只是执行一个32位的mull,并将结果的高32位(从%edx)放到返回值中。

这就是你想要的,对吧?听起来,您只需要对编译器进行优化;)可以通过消除中间变量将编译器推向正确的方向:

代码语言:javascript
复制
unsigned int umulhi32(unsigned int x, unsigned int y)
{
  return (unsigned int)(((unsigned long long)x * y)>>32);
}
票数 13
EN

Stack Overflow用户

发布于 2009-09-09 00:05:24

我不认为在标准的C/C++中有比你已经拥有的更好的方法来做到这一点。我要做的是编写一个简单的程序集包装器,返回您想要的结果。

并不是询问Windows,而是作为一个示例,尽管Windows有一个API,听起来它可以实现您想做的事情( 32位乘32位,同时获得完整的64位结果),但它将乘法实现为宏,执行您正在做的事情:

代码语言:javascript
复制
#define UInt32x32To64( a, b ) (ULONGLONG)((ULONGLONG)(DWORD)(a) * (DWORD)(b))
票数 3
EN

Stack Overflow用户

发布于 2009-09-09 00:06:09

在32位英特尔上,乘法会影响输出的两个寄存器。也就是说,无论您是否愿意,64位都是完全可用的。这仅仅是编译器是否聪明到能够利用它的一个函数。

现代编译器做了令人惊奇的事情,所以我的建议是尝试更多的优化标志,至少在Intel上是这样。您可能认为优化器可能知道处理器从32位乘32位产生64位值。

尽管如此,在某种程度上,我试图让编译器使用模块以及除法结果的红利,但1998年的旧Microsoft编译器还不够聪明,无法实现产生这两种结果的相同指令。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1396942

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档