1
double var = 0.;
for(int i = 0; i < 1000000 ; i++)
{
    var += sqrt(2.0);
}
std::cout << var << std::endl;

MSVC2012 では、最適化をオンにしたリリースで、sqrt(2.0) が 1*10^6 回呼び出されるのではなく、 call の値に置き換えられる可能性はありますか?

Asm はそのように見えますが、その解釈についてはよくわかりません:

; Line 6
    push    ebp
    mov ebp, esp
    sub esp, 84                 ; 00000054H
    push    ebx
    push    esi
    push    edi
; Line 8
    movsd   xmm0, QWORD PTR __real@0000000000000000
    movsd   QWORD PTR _var$[ebp], xmm0
; Line 9
    mov DWORD PTR _i$1[ebp], 0
    jmp SHORT $LN3@main
$LN2@main:
    mov eax, DWORD PTR _i$1[ebp]
    add eax, 1
    mov DWORD PTR _i$1[ebp], eax
$LN3@main:
    cmp DWORD PTR _i$1[ebp], 1000000        ; 000f4240H
    jge SHORT $LN1@main
; Line 11
    sub esp, 8
    movsd   xmm0, QWORD PTR __real@4000000000000000
    movsd   QWORD PTR [esp], xmm0
    call    _sqrt
    add esp, 8
    fstp    QWORD PTR tv85[ebp]
    movsd   xmm0, QWORD PTR tv85[ebp]
    addsd   xmm0, QWORD PTR _var$[ebp]
    movsd   QWORD PTR _var$[ebp], xmm0
; Line 12
    jmp SHORT $LN2@main

編集:

申し訳ありませんが、上記はデバッグ版でした....

; Line 7
    push    ebp
    mov ebp, esp
    and esp, -8                 ; fffffff8H
; Line 11
    movsd   xmm0, QWORD PTR __real@4000000000000000
    call    __libm_sse2_sqrt_precise
    movsd   xmm2, QWORD PTR ?var@@3NA
    mov eax, 1000000                ; 000f4240H
$LL3@main:
    movapd  xmm1, xmm0
    addsd   xmm2, xmm1
    dec eax
    jne SHORT $LL3@main
    movsd   QWORD PTR ?var@@3NA, xmm2
; Line 13
    mov esp, ebp
    pop ebp
    ret 0
4

2 に答える 2

5

そのアセンブリ ダンプを正しく読み取っていれば、コンパイラsqrtはデバッグ ビルドのループに残り、最適化されたビルドに移動しました。しかし、それはさらに攻撃的だった可能性があります。あなたが示すコードは合法的に最適化されている可能性があります

std::cout << "1414213.56238\n" << std::flush;

as-if ルールにより、コンパイラはプログラムの「観察可能な動作」を変更しないことをすべて実行できます。また、実行時間は観察可能な動作としてカウントされません。コンパイラは、すべての標準ライブラリ関数が何を行うかを「認識」し、それに基づいて最適化することもできます。

于 2012-12-24T19:38:21.370 に答える
1

明らかに期待どおりに呼び出されています:

movsd   QWORD PTR [esp], xmm0
call    _sqrt

編集:最適化フラグを変更せずに、コンパイラーが呼び出しを最適化しないように強制する方法の 1 つはsqrt()、コマンドラインで渡された値を渡すか、から読み込むことですstdin

double var = 0.;
double x;
cin >> x;
for(int i = 0; i < 1000000 ; i++) {
    var += sqrt(x);
}

コンパイル時に値がわからないため、呼び出しを最適化することは不可能になるはずです。ループは最適化されている可能性がありますが、カウンター値も渡すことができます。

于 2012-12-24T19:35:20.027 に答える