开发者

Performance difference with casting to double and increment

开发者 https://www.devze.com 2023-02-22 01:43 出处:网络
I\'m incrementing a counter, which I will need to use after the loop in double arithmetic. So, which would you expect to be faster? (Or too close to call?)

I'm incrementing a counter, which I will need to use after the loop in double arithmetic. So, which would you expect to be faster? (Or too close to call?)

Code 1:

double dubs = 3.14159265;
double d;
for(d=0; d<BIGNUM; d++) { /* do stuff not depending on d */ }
dubs /= d;

Code 2:

double dubs = 3.14159265;
int i;
for(i=0; i<BIGNUM; i++) { /* do stuff not depending on i */ }
dubs /= (double) i;

And does it depend on the size of BIGNUM? I know it would be a minuscule difference, but just found myself wondering in theory.

Bonus question: if it were C++, any change in your answer for using static_cast?

--Edit--

Ok, here's a sample code and assembler:

#define BIGNUM 1000000000
#define NUMLOOPS 1000

double test1()
{
    double dubs = 开发者_C百科3.14159265;
    double d;
    int k = 1;
    for(d=0; d<BIGNUM; d++) { k*= 2; }
    dubs /= d;
    return dubs;
}

double test2()
{
    double dubs = 3.14159265;
    int i;
    int k = 1;
    for(i=0; i<BIGNUM; i++) { k*= 2; }
    dubs /= (double)i;
    return dubs;
}

int main()
{
    double d1=0;
    double d2=0;
    int i;
    for(i=0; i<NUMLOOPS; i++)
    {
        d1 += test1();
        d2 += test2();
    }
}


_test1:
LFB2:
    pushq   %rbp
LCFI0:
    movq    %rsp, %rbp
LCFI1:
    subq    $48, %rsp
LCFI2:
    call mcount
    movabsq $4614256656543962353, %rax
    movq    %rax, -16(%rbp)
    movl    $1, -4(%rbp)
    movl    $0, %eax
    movq    %rax, -24(%rbp)
    jmp L2
L3:
    sall    -4(%rbp)
    movsd   -24(%rbp), %xmm0
    movsd   LC2(%rip), %xmm1
    addsd   %xmm1, %xmm0
    movsd   %xmm0, -24(%rbp)
L2:
    movsd   -24(%rbp), %xmm1
    movsd   LC3(%rip), %xmm0
    ucomisd %xmm1, %xmm0
    ja  L3
    movsd   -16(%rbp), %xmm0
    divsd   -24(%rbp), %xmm0
    movsd   %xmm0, -16(%rbp)
    movq    -16(%rbp), %rax
    movq    %rax, -40(%rbp)
    movsd   -40(%rbp), %xmm0
    leave
    ret


_test2:
LFB3:
    pushq   %rbp
LCFI3:
    movq    %rsp, %rbp
LCFI4:
    subq    $32, %rsp
LCFI5:
    call mcount
    movabsq $4614256656543962353, %rax
    movq    %rax, -16(%rbp)
    movl    $1, -8(%rbp)
    movl    $0, -4(%rbp)
    jmp L7
L8:
    sall    -8(%rbp)
    incl    -4(%rbp)
L7:
    cmpl    $99999, -4(%rbp)
    jle L8
    cvtsi2sd    -4(%rbp), %xmm1
    movsd   -16(%rbp), %xmm0
    divsd   %xmm1, %xmm0
    movsd   %xmm0, -16(%rbp)
    movq    -16(%rbp), %rax
    movq    %rax, -24(%rbp)
    movsd   -24(%rbp), %xmm0
    leave
    ret

Test is currently running....


As a double it probably doesn't matter, but if you'd used float, the first code fragment might not even work. Due to limited precision, after a while, incrementing a float will not change its value. Of course with (signed) integer types, you get UB on overflow, which is arguably worse.

Personally I would recommend always using integer types for a variable that contains something like a count/index that is naturally an integer. Using floating point types for this just feels wrong. But please remove the useless cast in the last line of the second fragment.

0

精彩评论

暂无评论...
验证码 换一张
取 消