哪个更快? ++,+ =或x + 1?

| 我正在使用C#(此问题对类似C ++的类似语言也有效),并且我试图找出最快,最有效的增量方法。在我的游戏中,它不只是一两个增量,而是每秒300个增量。就像屏幕上每个精灵的帧都在增加,我的rpg角色的速度和位置,摄像机的偏移量等等。所以我在想,哪种方法最有效?例如,我可以做的每动作增加5
y_pos
: 1。
Player.YPos += 5;
2。
Player.YPos = Player.YPos + 5;
3。
for (int i = 0; i < 5; i++)
{
    Player.YPos++;
}
哪一个最有效(最快)?     
已邀请:
        (特定于C#和C ++的答案可能会有很大差异。) 1和2是等效的。 3肯定会慢一些。 话虽如此,每秒仅执行300次,您就不会发现任何差异。您是否知道计算机在一秒钟内可以处理多少CPU和内存?通常,为清晰起见,编写代码是最重要的事情。绝对要担心性能-但只有当您有一种衡量它的方法时,才能a)告诉您是否需要担心,b)是否有任何更改实际上可以改善性能。 在这种情况下,我会说选项1是最清晰的,所以这就是我要使用的。     
        选项1和2将导致编译器生成相同的代码。选项3会慢很多。
i++
比than5ѭ甚至even6ѭ快是谬论。所有不错的编译器都会将这三个指令转换为相同的代码。 对于加法这样的微不足道的操作,请编写最清晰的代码,并使编译器担心它会很快。     
        编译器应为1和2生成相同的程序集,并且可能会展开选项3中的循环。遇到此类问题时,可以用来经验性测试发生情况的有用工具是查看生成的程序集由编译器。在g ++中,可以使用
-S
开关来实现。 例如,当使用命令
g++ -S inc.cpp
进行编译时(使用g ++ 4.5.2),选项1和2都会生成此汇编器。
main:
.LFB0:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    movq    %rsp, %rbp
    .cfi_offset 6, -16
    .cfi_def_cfa_register 6
    addl    $5, -4(%rbp)
    movl    $0, %eax
    leave
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
对于选项3,g ++产生的汇编器效率明显降低:
main:
.LFB0:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    movq    %rsp, %rbp
    .cfi_offset 6, -16
    .cfi_def_cfa_register 6
    movl    $0, -8(%rbp)
    jmp .L2
.L3:
    addl    $1, -4(%rbp)
    addl    $1, -8(%rbp)
.L2:
    cmpl    $4, -8(%rbp)
    setle   %al
    testb   %al, %al
    jne .L3
    movl    $0, %eax
    leave
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
但是,通过优化(即使是-O1),g ++也会针对所有3个选项生成此代码:
main:
.LFB0:
    .cfi_startproc
    leal    5(%rdi), %eax
    ret
    .cfi_endproc
g ++不仅展开了选项3中的循环,而且还使用lea指令在单个指令中进行加法运算,而不用费心于
mov
。 因此,g ++始终会为选项1和2生成相同的程序集。只有在您明确启用优化功能后,g ++才会为所有3个选项生成相同的程序集(这可能是您期望的行为)。 (尽管我从未尝试过,但看起来您也应该能够检查由C#生产的程序集)     
        它们是相同的:
static void Main(string[] args)
{
    int a = 0;
    a++;
    a +=1;
    a = a+1;
}
上面的代码在ILSpy中是:
private static void Main(string[] args)
{
    int a = 0;
    a++;
    a++;
    a++;
}
所有这些的IL也相同(在发布模式下):
.method private hidebysig static void  Main(string[] args) cil managed
{
    .entrypoint
    // Code size       15 (0xf)
    .maxstack  2
    .locals init ([0] int32 a)
    IL_0000:  ldc.i4.0
    IL_0001:  stloc.0
    IL_0002:  ldloc.0
    IL_0003:  ldc.i4.1
    IL_0004:  add
    IL_0005:  stloc.0
    IL_0006:  ldloc.0
    IL_0007:  ldc.i4.1
    IL_0008:  add
    IL_0009:  stloc.0
    IL_000a:  ldloc.0
    IL_000b:  ldc.i4.1
    IL_000c:  add
    IL_000d:  stloc.0
    IL_000e:  ret
} // end of method Program::Main
    
        选项1和2在编译后将产生相同的代码。选项3会慢很多,因为它会导致涉及for循环的更多代码。     

要回复问题请先登录注册