【问题标题】:Division performance for a x32 ELF on a x64 OSx64 操作系统上 x32 ELF 的除法性能
【发布时间】:2019-08-07 08:23:48
【问题描述】:

在以下示例中,在 64 位架构上运行 32 位 ELF 更快,但我不明白为什么。我尝试了两个示例,一个使用除法,另一个使用乘法。表现符合预期,但该部门的表现令人惊讶。

我们在汇编中看到编译器正在调用 _alldiv,它在 32 位架构上模拟 64 位除法,因此它必须比简单地使用汇编指令 idiv 慢。所以我不明白我得到的结果:

我的设置是:Windows 10 x64、Visual Studio 2019

计时码我使用Measure-Command { .\out.exe }:

  • 乘法
    • 32 位 ELF:3360 毫秒
    • 64 位 ELF:1469 毫秒
    • 32 位 ELF:7383 毫秒
    • 64 位 ELF:8567 毫秒

代码

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <limits.h>
#include <Windows.h>

volatile int64_t m = 32;
volatile int64_t n = 12;
volatile int64_t result;

int main(void)
{
    for (size_t i = 0; i < (1 << 30); i++)
    {
#       ifdef DIVISION
        result = m / n;
#       else 
        result = m * n;
#       endif
        m += 1;
        n += 3;
    }
}

64位反汇编(除法)

    for (size_t i = 0; i < (1 << 30); i++)
00007FF60DA81000  mov         r8d,40000000h  
00007FF60DA81006  nop         word ptr [rax+rax]  
    {
        result = m / n;
00007FF60DA81010  mov         rcx,qword ptr [n (07FF60DA83038h)]  
00007FF60DA81017  mov         rax,qword ptr [m (07FF60DA83040h)]  
00007FF60DA8101E  cqo  
00007FF60DA81020  idiv        rax,rcx  
00007FF60DA81023  mov         qword ptr [result (07FF60DA83648h)],rax  
        m += 1;
00007FF60DA8102A  mov         rax,qword ptr [m (07FF60DA83040h)]  
00007FF60DA81031  inc         rax  
00007FF60DA81034  mov         qword ptr [m (07FF60DA83040h)],rax  
        n += 3;
00007FF60DA8103B  mov         rax,qword ptr [n (07FF60DA83038h)]  
00007FF60DA81042  add         rax,3  
00007FF60DA81046  mov         qword ptr [n (07FF60DA83038h)],rax  
00007FF60DA8104D  sub         r8,1  
00007FF60DA81051  jne         main+10h (07FF60DA81010h)  
    }
}

32位反汇编(除法)

    for (size_t i = 0; i < (1 << 30); i++)
00A41002  mov         edi,40000000h  
00A41007  nop         word ptr [eax+eax]  
    {
        result = m / n;
00A41010  mov         edx,dword ptr [n (0A43018h)]  
00A41016  mov         eax,dword ptr ds:[00A4301Ch]  
00A4101B  mov         esi,dword ptr [m (0A43020h)]  
00A41021  mov         ecx,dword ptr ds:[0A43024h]  
00A41027  push        eax  
00A41028  push        edx  
00A41029  push        ecx  
00A4102A  push        esi  
00A4102B  call        _alldiv (0A41CD0h)  
00A41030  mov         dword ptr [result (0A433A0h)],eax  
00A41035  mov         dword ptr ds:[0A433A4h],edx  
        m += 1;
00A4103B  mov         eax,dword ptr [m (0A43020h)]  
00A41040  mov         ecx,dword ptr ds:[0A43024h]  
00A41046  add         eax,1  
00A41049  mov         dword ptr [m (0A43020h)],eax  
00A4104E  adc         ecx,0  
00A41051  mov         dword ptr ds:[0A43024h],ecx  
        n += 3;
00A41057  mov         eax,dword ptr [n (0A43018h)]  
00A4105C  mov         ecx,dword ptr ds:[0A4301Ch]  
00A41062  add         eax,3  
00A41065  mov         dword ptr [n (0A43018h)],eax  
00A4106A  adc         ecx,0  
00A4106D  mov         dword ptr ds:[0A4301Ch],ecx  
00A41073  sub         edi,1  
00A41076  jne         main+10h (0A41010h)  
    }
}

编辑

为了进一步调查Chris Dodd,我稍微修改了我的代码如下:

volatile int64_t m = 32000000000;
volatile int64_t n = 12000000000;
volatile int64_t result;

这次我有这些结果:

    • 32 位 ELF:22407 毫秒
    • 64 位 ELF:17812 毫秒

【问题讨论】:

  • 对 _alldiv 的转储感到好奇,看看它在做什么?可以是小整数的缓存表。 idiv 是 x86 上的已知猪,所以可能更快?
  • @MichaelDorgan 看来__alldiv 是:jbox.dk/sanos/source/lib/lldiv.asm.html
  • MSVC 可以制作 ELF 可执行文件吗? WSL 甚至无法运行 32 位 Linux/ELF 可执行文件(仅限 x86-64),那么您是如何运行它的呢?另外,为什么要通过使输入变量volatile 以及递增它们来引入存储/重新加载内存依赖关系?
  • @nowox: 有点 OT 注意:如果你还不知道,你应该看看 Agner Fog 的主页:agner.org/optimize。它包含很多关于这个主题的有价值的资源......
  • 您为什么使用术语“ELF”?这是 Linux 和 Unix 上使用的可执行格式的名称。这只是 EXE / 可执行文件的错字吗?对于您可能正在制作的普通 Windows .exe 文件,Windows 使用 PE/COFF 可执行格式,而不是 ELF。

标签: c windows performance x86 division


【解决方案1】:

如果您查看instruction timings for x86 processors,会发现在最新的英特尔处理器上,64 位除法的成本是 32 位除法的 3-4 倍——如果您查看 alldiv 的内部结构(链接在上面的 cmets 中),对于始终适合 32 位的值,它将使用单个 32 位除法...

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-06
  • 2012-09-29
  • 2019-10-25
  • 2013-10-22
  • 1970-01-01
相关资源
最近更新 更多