在if的其他情况下,它会更快/使用更少的内存吗?

时间:2017-11-06 09:14:16

标签: c performance memory

最近我在我的CS研究中得到了一个代码示例(参见代码#1),并且如果我的第二版代码更快或使用更少的内存,我会尝试引出。 你对我的问题有答案吗?

// Code #1
double f(double b, double x)
{
    double s;
    if (x == 0.0)
        s = 1.0;
    else
        s = sin(x)/x;
    return s + b;
}

// Code #2
double f(double b, double x)
{
    // I thought this would be faster and using less memory due to 
    // not declaring a new double
    if (x == 0.0)
        return 1.0 + b;
    else
        return sin(x)/x + b;
}

谢谢你们的帮助。

4 个答案:

答案 0 :(得分:1)

这取决于编译器和优化标志。一般来说,两个代码都会给出相同的结果。

答案 1 :(得分:1)

我已经生成了这两种情况的汇编。

案例1:

        push    rbp
        mov     rbp, rsp
        sub     rsp, 48
        movsd   QWORD PTR [rbp-24], xmm0
        movsd   QWORD PTR [rbp-32], xmm1
        pxor    xmm0, xmm0
        ucomisd xmm0, QWORD PTR [rbp-32]
        jp      .L2
        pxor    xmm0, xmm0
        ucomisd xmm0, QWORD PTR [rbp-32]
        jne     .L2
        movsd   xmm0, QWORD PTR .LC1[rip]
        movsd   QWORD PTR [rbp-8], xmm0
        jmp     .L4
.L2:
        mov     rax, QWORD PTR [rbp-32]
        mov     QWORD PTR [rbp-40], rax
        movsd   xmm0, QWORD PTR [rbp-40]
        call    sin
        divsd   xmm0, QWORD PTR [rbp-32]
        movsd   QWORD PTR [rbp-8], xmm0
.L4:
        movsd   xmm0, QWORD PTR [rbp-8]
        addsd   xmm0, QWORD PTR [rbp-24]
        leave
        ret
.LC1:
        .long   0
        .long   1072693248

案例2:

        push    rbp
        mov     rbp, rsp
        sub     rsp, 32
        movsd   QWORD PTR [rbp-8], xmm0
        movsd   QWORD PTR [rbp-16], xmm1
        pxor    xmm0, xmm0
        ucomisd xmm0, QWORD PTR [rbp-16]
        jp      .L2
        pxor    xmm0, xmm0
        ucomisd xmm0, QWORD PTR [rbp-16]
        jne     .L2
        movsd   xmm1, QWORD PTR [rbp-8]
        movsd   xmm0, QWORD PTR .LC1[rip]
        addsd   xmm0, xmm1
        jmp     .L4
.L2:
        mov     rax, QWORD PTR [rbp-16]
        mov     QWORD PTR [rbp-24], rax
        movsd   xmm0, QWORD PTR [rbp-24]
        call    sin
        divsd   xmm0, QWORD PTR [rbp-16]
        addsd   xmm0, QWORD PTR [rbp-8]
.L4:
        leave
        ret
.LC1:
        .long   0
        .long   1072693248

没有区别。因此,它们之间没有速度优化。因此,代码优化依赖于编译器。

答案 2 :(得分:1)

只声明变量不仅仅是占用记忆的东西。

int a = 1 + 2;
int b = 3;
int c = a + b;

此代码将采用与以下代码相同的值

int c = 1 + 2 + 3;

因为最终处理器将在单核中一次执行一个操作 第二个代码添加两个数字并将其保存在堆栈中,然后取第三个数字添加前两个数字的结果。

答案 3 :(得分:1)

简短回答:别担心!

答案很长:

sin将占用此功能的最多时间,因此一些额外的指令(如果有的话)将不会产生任何明显的影响。

虽然有疑问,look生成的代码。

在x86_64上使用GCC 6.3,第一个版本使用1个寄存器(xmm2),但优化器能够更好地重新排序指令。

版本1:

        ucomisd xmm1, QWORD PTR .LC1[rip]
        movapd  xmm2, xmm0
        jp      .L5
        movsd   xmm0, QWORD PTR .LC0[rip]
        je      .L7
.L5:
        movapd  xmm0, xmm1
        sub     rsp, 24
        movsd   QWORD PTR [rsp+8], xmm2
        movsd   QWORD PTR [rsp], xmm1
        call    sin
        movsd   xmm1, QWORD PTR [rsp]
        movsd   xmm2, QWORD PTR [rsp+8]
        add     rsp, 24
        divsd   xmm0, xmm1
        addsd   xmm0, xmm2
        ret
.L7:
        addsd   xmm0, xmm2
        ret

第2版:

        ucomisd xmm1, QWORD PTR .LC0[rip]
        jp      .L2
        je      .L10
.L2:
        sub     rsp, 24
        movsd   QWORD PTR [rsp], xmm0
        movapd  xmm0, xmm1
        movsd   QWORD PTR [rsp+8], xmm1
        call    sin
        movsd   xmm1, QWORD PTR [rsp+8]
        divsd   xmm0, xmm1
        addsd   xmm0, QWORD PTR [rsp]
        add     rsp, 24
        ret
.L10:
        addsd   xmm0, QWORD PTR .LC1[rip]
        ret

那么这两个版本之间的性能差异有多大?只有性能测试才能确定(但我的猜测是你赢了但没有看到任何区别)。