5

奇妙な問題が 1 つあります。次のコードがあります。

template<clss index, class policy>
inline int CBase<index,policy>::func(const A& test_in, int* srcPtr ,int* dstPtr)
{
    int width = test_in.width();
    int height = test_in.height();

    double d = 0.0; //here is the problem
    for(int y = 0; y < height; y++)
    {

        //Pointer initializations

        //multiplication involving y
        //ex: int z = someBigNumber*y + someOtherBigNumber;
        for(int x = 0; x < width; x++)
        {
            //multiplication involving x
        //ex: int z = someBigNumber*x + someOtherBigNumber;
            if(soemCondition)
            {
                // floating point calculations
            }
            *dstPtr++ = array[*srcPtr++];
        }
    }
}

内側のループは約 200,000 回実行され、関数全体が完了するまでに 100 ミリ秒かかります。(AQTimer を使用してプロファイリング)

double d = 0.0;外側のループの外側で未使用の変数を見つけ、 それを削除しました。この変更後、突然、同じ回数の実行でメソッドが 500 ミリ秒かかるようになりました。(5倍遅い)。

この動作は、異なるプロセッサ タイプの異なるマシンで再現可能です。(Core2、デュアルコア プロセッサ)。

最適化レベル の VC6 コンパイラを使用していますO2。使用されるその他のコンパイラ オプションは次のとおりです。

 -MD -O2 -Z7 -GR -GX -G5 -X -GF -EHa

コンパイラの最適化を疑い、コンパイラの最適化を削除しました/O2。その後、関数が正常になり、古いコードとして 100ms かかっています。

誰かがこの奇妙な振る舞いに光を当てることができますか?

未使用の変数を削除すると、コンパイラの最適化によりパフォーマンスが低下するのはなぜですか?

注: アセンブリ コード (変更前と変更後) は同じように見えました。

4

3 に答える 3

5

変更の前後でアセンブリ コードが同じように見える場合、エラーは何らかの形で関数のタイミングに関連しています。

于 2010-04-29T06:45:01.147 に答える
4

VC6 は非常にバグが多いです。いくつかのケースで誤ったコードを生成することが知られており、オプティマイザもそれほど高度ではありません。コンパイラは 10 年以上前のものであり、何年もサポートされていません。

つまり、答えは「バグのあるコンパイラを使用しています。特に最適化が有効になっている場合は、バグのある動作が予想されます」です。

最新のコンパイラにアップグレードする (または単にコードをテストする) ことはオプションではないと思いますか?

明らかに、生成されたアセンブリは同じにすることはできません。そうしないと、パフォーマンスの違いはありません。

唯一の問題は、違いがどこにあるかです。また、バグのあるコンパイラでは、コードのまったく無関係な部分が突然別の方法でコンパイルされて壊れる可能性があります。ただし、ほとんどの場合、この関数用に生成されたアセンブリ コードは同じではなく、その違いは非常に微妙であるため、気付かないほどです。

于 2010-04-29T17:18:18.363 に答える
1

widthandheightを const {unsigned} int として宣言します。{高さと幅が負になることはないため、符号なしを使用する必要があります}

const int width = test_in.width();
const int height = test_in.height();

これは、コンパイラの最適化に役立ちます。値を asconstにすると、変更されないことがわかっているため、コードまたはレジスタに配置できます。また、変数が変化しているかどうかをコンパイラが推測する必要がなくなります。

未使用のバージョンと未使用のバージョンのアセンブリ コードを印刷することをお勧めしますdouble。これにより、コンパイラの思考プロセスについての洞察が得られます。

于 2010-04-29T16:56:34.710 に答える