最適化の罠

割り込み通知の処理で、どんなコードを書けば、最短で通知できるかテストするために、手始めに次のようなコードを書きました。

DWORD WINAPI WhileLoopThread(LPVOID data)
{
    int& i = *((int*)data);
    Beep(1000, 200);
    Sleep(1000);
    Beep(1000, 200);
    timer.Reset();
    i = 1;
    return 1;
}


void CSyncObjectDlg::OnBnClickedButtonWhileLoop()
{
    // While ループを使用して処理待ちをします。
    int i=0;
    HANDLE hThread = ::CreateThread(NULL, NULL, WhileLoopThread, &i, NULL, NULL);
    while(1)
    {
        if(i==1)
        {
            double t = timer.GetDeltaT();
            CString strMsg;
            strMsg.Format("経過時間:%f", t);
            MessageBox(strMsg);
            break;
        }
    }
    ::CloseHandle(hThread);
}


呼び出し側では、while の無限ループを延々と繰り返し、変数 i が 1 になったことを判定し、なにがしかの処理を実行します。

このコードをデバッグモードでビルドすると、次のコードが生成されました。
(混合モードで表示しています。)

最適化前:
    while(1)
00415A12  mov         eax,1 
00415A17  test        eax,eax 
00415A19  je          CSyncObjectDlg::OnBnClickedButtonForLoop+102h (415AB2h) 
    {
        if(i==1)
00415A1F  cmp         dword ptr [i],1 
00415A23  jne         CSyncObjectDlg::OnBnClickedButtonForLoop+0FDh (415AADh) 
        {
            double t = timer.GetDeltaT();


これはちゃんと動きました。
昨今はCPUが増えたので、パフォーマンスに優れるなら、こんな待ち方もありかな~
なんて思っていました。
反応は、5~10 μs となかなかの応答をしてくれます。

では、最適化後のリリースビルドならもっと早いんじゃないか?と思い、リリースでビルドしてみると、、、
こんなコードができました。

最適化後:
004011CE  mov         eax,dword ptr [esp+0Ch] 
    while(1)
    {
        if(i==1)
004011D2  cmp         eax,1 
004011D5  jne         CSyncObjectDlg::OnBnClickedButtonForLoop+42h (4011D2h) 
        {
            double t = timer.GetDeltaT();
004011D7  mov         ecx,offset timer (4050F8h) 
004011DC  call        CFreqTimer::GetDeltaT (401590h) 
004011E1  fstp        qword ptr [esp+10h] 


実行してみると、、、

無限ループじゃん!!

処理を感知しません。

解説すると、、、
mov eax,dword ptr [esp+0Ch]

で、変数 i の内容を eax レジスタにコピーした後、ループの度に
cmp eax,1

というコードで、eax レジスタと 数値の1を比較して、偽なら、もう一度 eax レジスタと 数値の1を比較、、、
を延々と繰り返します。。。

あほか。。。

別スレッドは、変数 i は変更するけど、eax レジスタを変更する訳ではないので、このままだと永遠に eax レジスタは0のままになってしまいます。

コンパイラの最適化がこんなコードをはき出すなんて。。。

プログラムを書くのが恐くなりました。

今後は、リリースビルドでも最適化はOFFにしようかな。。。。
[PR]
by isoq | 2007-02-26 13:04 | C/C++/Win32
e87.com(千趣会イイハナ) 花を贈るなら日比谷花壇
<< ロマンスカー グッピーがぁ、、、グッピーがぁ... >>