C 为什么取消引用会使我的程序更快?

C 为什么取消引用会使我的程序更快?,c,C,考虑以下测试程序: [编辑]以下是10次执行的平均值: case1.c 2.70364 case2.c 2.57091 case3.c 2.57000 为什么第一个测试用例的执行时间更大,这似乎是最简单的? 我当前的体系结构是x86虚拟机(Archlinux)。我通过gcc(4.8.0)和clang(3.3)获得了这些结果 [edit 1]生成的汇编代码几乎相同,只是第二个和第三个汇编代码的指令比第一个汇编代码多 [编辑2]这些性能是可复制的(在我的系统上)。每次执行将具有相同的数量

考虑以下测试程序:

[编辑]以下是10次执行的平均值:

case1.c
2.70364

case2.c
2.57091

case3.c
2.57000
为什么第一个测试用例的执行时间更大,这似乎是最简单的?

我当前的体系结构是x86虚拟机(Archlinux)。我通过gcc(4.8.0)和clang(3.3)获得了这些结果

[edit 1]生成的汇编代码几乎相同,只是第二个和第三个汇编代码的指令比第一个汇编代码多

[编辑2]这些性能是可复制的(在我的系统上)。每次执行将具有相同的数量级


[编辑3]我并不真正关心未优化程序的性能,但我不明白为什么它会变慢,我很好奇。

很难说这是否是原因,因为我在猜测,而您没有给出一些具体信息(例如您使用的目标)。但是,当我使用x86目标编译而不进行优化时,我看到的是
iterations
变量递减的以下序列:

案例1:

L3:
    sub DWORD PTR [esp+12], 1
L2:
    cmp DWORD PTR [esp+12], 0
    jg  L3
案例2:

L3:
    mov eax, DWORD PTR [esp+12]
    mov eax, DWORD PTR [eax]
    lea edx, [eax-1]
    mov eax, DWORD PTR [esp+12]
    mov DWORD PTR [eax], edx
L2:
    mov eax, DWORD PTR [esp+12]
    mov eax, DWORD PTR [eax]
    test    eax, eax
    jg  L3
您在案例1中看到的一个大区别是
L3
处的指令读取和写入内存位置。它后面紧接着一条指令,该指令读取刚刚写入的相同内存位置。这种指令序列(与写入下一条指令时立即使用的内存位置相同)在现代CPU中经常导致某种管道暂停

您将注意到,在案例2中不存在紧跟着相同位置的读取的写操作


同样,这个答案是一种有根据的推测。

您是否尝试查看生成的代码?为什么您关心未优化代码的性能?您是否尝试过以不同的顺序运行它们?这些是单次放炮时间,还是大量运行的平均值?@EJP这些性能是可复制的。每次执行都将具有相同的数量级(测试多次)。@MaëlNison:在现代CPU上,指令数与性能的相关性很弱。由于内存暂停、缓存性能、寄存器依赖关系、分支预测等其他影响,您还没有指定体系结构,但假设它是x86或x64,则执行指令并不需要固定的时间。因此,指令的数量绝对是衡量速度的一个毫无意义的指标。@snf事实是,怀疑这个问题的答案是否有趣到足以让任何人满意with@aaronman:我没有-我认为即使我看到了OP结果的不同,也可以很容易地用各种其他系统效应来解释。我使用的是GCC4.8.0编译器-我认为x86目标的代码生成器与
-O0
非常相似。处理器管道如何快速连续地处理对同一位置的读/写操作(即使不是精确的下一条指令)的细节对我和地球上的大多数人来说都是个谜。@aaronman:我同意,除了可能之外,很难找到一个满意的答案“当以特定模式访问内存时,处理器可能会暂停”。我想每个人都想成为下一个@Sayakiss,你也可以使用在线,这太棒了。
case1.c
real    0m2.698s
user    0m2.690s
sys     0m0.003s

case2.c
real    0m2.574s
user    0m2.567s
sys     0m0.000s

case3.c
real    0m2.566s
user    0m2.560s
sys     0m0.000s
case1.c
2.70364

case2.c
2.57091

case3.c
2.57000
L3:
    sub DWORD PTR [esp+12], 1
L2:
    cmp DWORD PTR [esp+12], 0
    jg  L3
L3:
    mov eax, DWORD PTR [esp+12]
    mov eax, DWORD PTR [eax]
    lea edx, [eax-1]
    mov eax, DWORD PTR [esp+12]
    mov DWORD PTR [eax], edx
L2:
    mov eax, DWORD PTR [esp+12]
    mov eax, DWORD PTR [eax]
    test    eax, eax
    jg  L3