为什么减去比mod慢?

时间:2009-01-05 22:35:07

标签: .net

在那个具体案例中

    Const debugTime As String = "hh:mm:ss.fffffff"
    Dim i As Integer

    Debug.Print("Start " & Now.ToString(debugTime))
    For i = 0 To 4000000
        j = 5 - 4
    Next
    Debug.Print("End " & Now.ToString(debugTime))

    Debug.Print("Start " & Now.ToString(debugTime))
    For i = 0 To 4000000
        j = 5 Mod 4
    Next
    Debug.Print("End " & Now.ToString(debugTime))

结果

Start 05:33:39.8281250

结束05:33:39.8437500

Start 05:33:39.8437500

结束05:33:39.8437500

*编辑*

修改代码使其看起来像那样

    Const debugTime As String = "hh:mm:ss.fffffff"
    Dim i As Long, j As Integer
    Dim r As Random

    r = New Random(1)
    Debug.Print("Start " & Now.ToString(debugTime))
    For i = 0 To 400000000
        j = 5 - r.Next(1, 5)
    Next
    Debug.Print("End " & Now.ToString(debugTime))

    r = New Random(1)
    Debug.Print("Start " & Now.ToString(debugTime))
    For i = 0 To 400000000
        j = 5 Mod r.Next(1, 5)
    Next
    Debug.Print("End " & Now.ToString(debugTime))

现在减号更快......

Start 05:49:25.0156250

结束05:49:35.7031250

开始05:49:35.7031250

结束05:49:48.2187500

3 个答案:

答案 0 :(得分:7)

  • 使用如此微小的时间间隔进行基准测试可以让您对计时器粒度问题持开放态度,这就是您在此处所看到的。
  • 你的代码实际上并没有计算任何东西,因为你两次都有一个常数。

事实上,这个小的基准测试操作非常棘手 - 为了确保编译器和JIT编译器都没有优化,你真的想让它以某种方式使用结果,但这会非常显着地影响结果。

答案 1 :(得分:5)

编译器会将它们优化为赋值。很小的差异可能是另一个因素的结果。

更新: 我在Mac OS X,Intel 64架构上写了一个基准测试。巨大的差异:

a.asm:汇集yasm -f macho64 a.asm

SECTION .text
global _bmod, _bmin
_bmod:  push rdx
    push rbx
    mov rcx, 1000000000
    mov rdi, 5
    mov rsi, 4
.bmod:  mov rax, rdi
    mov rbx, rsi
    xor rdx, rdx
    div rbx             ; div instruction stores the mod in rdx.
    dec rcx
    jnz .bmod
    pop rbx
    pop rdx
    ret

_bmin:  push rdx
    push rbx
    mov rcx, 1000000000
    mov rdi, 5
    mov rsi, 4
.bmin:  mov rax, rdi
    mov rbx, rsi
    sub rax, rbx
    dec rcx
    jnz .bmin
    pop rbx
    pop rdx
    ret

a.c:使用gcc -m64 a.c a.o

进行编译
#include <time.h>
#include <stdio.h>

void bmod();
void bmin();

main() {
    time_t timex,timex2;
    time(&timex);
    bmod();
    time(&timex2);
    printf("Mod: %d\n", timex2 - timex);
    time(&timex);
    bmin();
    time(&timex2);
    printf("Min: %d\n", timex2 - timex);
}

我在MacBook Air上运行时的结果:

Mehrdad-Air:~ Mehrdad$ yasm -f macho64 a.asm 
Mehrdad-Air:~ Mehrdad$ gcc -m64 -O0 a.c a.o
Mehrdad-Air:~ Mehrdad$ ./a.out 
Mod: 14
Min: 2

如您所见,模数比减法慢一个数量级。

答案 2 :(得分:3)

除了Jon Skeet所说的,我通常使用System.Diagnostics.Stopwatch()进行基准测试,因为我发现高速计数器往往比仅仅参考DateTime更可靠.Now

  Dim t = new System.Diagnostics.Stopwatch()
  t.Start

  ''Do Stuff...

  Debug.Print(t.Elapsed)
  t.Stop

编辑:(或根据Jon在评论中的建议:

  Dim t = System.Diagnostics.Stopwatch.StartNew

  ''Do Stuff...

  Debug.Print(t.Elapsed)
  t.Stop