代码之家  ›  专栏  ›  技术社区  ›  SPWorley

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

  •  10
  • SPWorley  · 技术社区  · 17 年前

    许多CPU都有单个程序集操作码用于返回 高的

    例如,在PowerPC上 mulhw

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

    unsigned int umulhi32(unsigned int x, unsigned int y)
    {
      unsigned long long xx=x;
      xx*=y;
      return (unsigned int)(xx>>32);
    }
    

    但这比常规的32乘32的乘法慢11倍多,因为即使在乘法中,我也使用了overkill 64位数学。

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

    这显然是错误的 不 最好使用BigInteger库来解决(这是一种过分的方法,会产生巨大的开销)。

    PMULHUW ,16x16->此版本的顶级16位版本,但不是32x32->前32个版本,就像我正在寻找的。

    3 回复  |  直到 8 年前
        1
  •  13
  •   caf    17 年前

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

    umulhi32:
            pushl   %ebp
            movl    %esp, %ebp
            movl    12(%ebp), %eax
            mull    8(%ebp)
            movl    %edx, %eax
            popl    %ebp
            ret
    

    这只是一个32位 mull 并将结果的高32位(从 %edx )输入返回值。

    unsigned int umulhi32(unsigned int x, unsigned int y)
    {
      return (unsigned int)(((unsigned long long)x * y)>>32);
    }
    
        2
  •  3
  •   Michael Burr    17 年前

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

    #define UInt32x32To64( a, b ) (ULONGLONG)((ULONGLONG)(DWORD)(a) * (DWORD)(b))
    
        3
  •  2
  •   Matthias Wandel    17 年前

    在32位intel上,乘法会影响输出的两个寄存器。也就是说,64位是完全可用的,无论您是否想要它。这只是编译器是否足够聪明来利用它的一个函数。

    现代编译器做的事情非常惊人,所以我的建议是再多做一些优化标记的实验,至少在英特尔上是这样。您可能会认为优化器可能知道处理器从32×32位生成64位值。

    这就是说,在某个时刻,我试图让编译器在除法结果上使用模和除法,但1998年的老Microsoft编译器不够聪明,无法实现相同的指令同时产生两种结果。