Programmatically, how to write an unoptimized code to calculate the sum of 10 integers?

自作多情 提交于 2019-12-14 03:27:01

问题


In Java, C, or C++, how to write an unoptimized code to calculate the sum of 10 integers (from 0 to 9) programmatically?

For example, I use the following code but it is seems that both codes (the ones labeled as //Baseline and //Method #1) are optimized by the compiler at the compile time and the total variables are converted to constants before runtime. I confirmed that by comparing the time1 and time2 which are similar.

My question is:

Programmatically, how to sum the 10 numbers and force the compiler not to optimize the code (no constant propagation/folding, for example) to avoid calculating the sum at compile time and force it to happen only at runtime?

       long start, end, time1, time2, total;

    //Baseline
    start = System.nanoTime();
    total = (0+1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9);
    end = System.nanoTime();
    System.out.println("********************* The sum is " + total);
    time1 =  end - start;
    System.out.println("********************* start=" + start + " end=" + end + " time=" + time1);

    //Method #1
    start = System.nanoTime();
    total = (a0() + a1() + a2() + a3() + a4() + a5() + a6() + a7() + a8() + a9());
    end = System.nanoTime();
    System.out.println("********************* The sum is " + total);
    time2 =  end - start;
    System.out.println("********************* start=" + start + " end=" + end + " time=" + time2);

}
private int a0()
{
    return 0;
}
private int a1()
{
    return 1;
}
private int a2()
{
    return 2;
}
private int a3()
{
    return 3;
}
private int a4()
{
    return 4;
}
private int a5()
{
    return 5;
}
private int a6()
{
    return 6;
}
private int a7()
{
    return 7;
}
private int a8()
{
    return 8;
}
private int a9()
{
    return 9;
}

Updated Requirements:

(1) Only for Java using Dalvik compiler

(2) Only primitive variables but nested functions (methods) are acceptable

(3) No volatile

(4) No loop, jump, or wait statements

By the way, I tried the suggested C and C++ suggestions below but non of them seem to work with Dalvik compiler where it converts the addition expression to a constant.


回答1:


You can do this in C pretty easily by just disabling optimisations when you compile. Take this C program:

#include <stdio.h>

int main(int argc, char *argv[]) {
    int sum = 0;
    for (int i = 0; i < 10; i++) {
        sum += i;
    }
    printf("%d\n", sum);
    return 0;
}

And compile with gcc -O0 program.c. -O0 tells GCC not to optimise your code. If you take a look at the outputted assembly (which you can do by adding -S as an argument to compilation), you can see that it is indeed summing the first 10 numbers:

...
LBB0_1:                                 ## =>This Inner Loop Header: Depth=1
    cmpl    $10, -24(%rbp)
    jge LBB0_4
## BB#2:                                ##   in Loop: Header=BB0_1 Depth=1
    movl    -24(%rbp), %eax
    addl    -20(%rbp), %eax
    movl    %eax, -20(%rbp)
## BB#3:                                ##   in Loop: Header=BB0_1 Depth=1
    movl    -24(%rbp), %eax
    addl    $1, %eax
    movl    %eax, -24(%rbp)
    jmp LBB0_1
...

You can see the jump at the end of the snippet back to the start of the loop, and the conditional jump at the start of the loop to check i < 10. If you take a look at the optimised assembly code (compiling with gcc -O3 -S program.c), you can see GCC unrolls the loop and calculates the sum at compile time:

...
movl    $45, %esi
...

I have no idea why you want to do this though.




回答2:


You could use an array (which is an object type in Java), and then in Java 8+ you could use IntStream.sum(). Something like,

int[] arr = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
int sum = IntStream.of(arr).sum();

or

int sum = IntStream.range(0, 10).sum();



回答3:


godbolt is a pretty cool online C++ compiler that conveniently shows assembly output. I tried gcc, clang and icc and all of them optimised 1 + 2 + 3... source code into a compile time result even at -O0, but if you code it like this:

// Type your code here, or load an example.
int main()
{
    register int sum = 1;
    sum += 2;
    sum += 3;
    sum += 4;
    sum += 5;
    sum += 6;
    sum += 7;
    sum += 8;
    sum += 9;
    return sum;
}

...you can get output like this (GCC 5.3.0 in this case)...

main:
    pushq   %rbp
    movq    %rsp, %rbp
    pushq   %rbx
    movl    $1, %ebx
    addl    $2, %ebx
    addl    $3, %ebx
    addl    $4, %ebx
    addl    $5, %ebx
    addl    $6, %ebx
    addl    $7, %ebx
    addl    $8, %ebx
    addl    $9, %ebx
    movl    %ebx, %eax
    popq    %rbx
    popq    %rbp
    ret

Clearly each add is being done separately. This also avoids overheads of loop control which you'd have if you introduced a for loop with bounds only known at runtime.

Still, what does it mean? There's no guarantee that the compiler will produce similar assembly given the same number of runtime-known variables....




回答4:


What you want is volatile....

#include <stdio.h>

int main ( void ) {

    volatile int n = 0;

    n += 1; n += 2; n += 3; n += 4; n += 5;
    n += 6; n += 7; n += 8; n += 9; n += 10;
    printf("%d\n", n);
    return 0;
}

[EDIT] The addition appears to take place in a register, but there are two moves for each add:

    movl    -4(%ebp), %eax
    addl    $2, %eax
    movl    %eax, -4(%ebp)


来源:https://stackoverflow.com/questions/34734660/programmatically-how-to-write-an-unoptimized-code-to-calculate-the-sum-of-10-in

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!