1

C# から ummanaged dll を呼び出しているので、C# と C での for ループのパフォーマンスについてテストを行いました。

結果は、ループがより大きな範囲に行くにつれて、C# のパフォーマンスが C に比べて低下するという点で私を驚かせました.狭い範囲では、C# は C よりも優れたパフォーマンスを示しました....しかし、for ループの上位範囲として増加すると、C と比較して C# のパフォーマンスが低下します....

これが私のテストコードです....

    [DllImport("Testing.dll", CallingConvention =  CallingConvention.Cdecl)]
    public static extern int SumLoop(int lowLimit, int highLimit);

    public static void Main(string[] args)
    {
        const int LowerRange = 1;
        const int HigherRange = 1000000;

        // Test with C# For Loop
        var watch1 = new Stopwatch();
        watch1.Start();
        int sum = 0;
        for (int i = LowerRange; i <= HigherRange; i++)
        {
            sum += i;
        }
        watch1.Stop();

        long elapseTime1 = watch1.ElapsedMilliseconds;

        // Test with C-for loop
        var watch2 = new Stopwatch();
        watch2.Start();
        int sumFromC = SumLoop(LowerRange , HigherRange);
        long elapseTime2 = watch2.ElapsedMilliseconds;
   }

Testing.dll:

__declspec(dllexport) int SumLoop(int lowLimit, int highLimit)
{
    int idx;
    int totalSum = 0;
    for(idx = lowLimit;idx<= highLimit; idx= idx +1)
    {
        totalSum += idx;
    }
    return totalSum;
}

テスト結果:

テスト 1 :

より高い範囲: 1000000

C# ループ: 4 ミリ秒

Cループ:9ミリ秒

テスト 2 :

より高い範囲: 10000000

C# ループ: 53 ミリ秒

Cループ:36ミリ秒

テスト 3 :

より高い範囲: 100000000

C# ループ: 418 ミリ秒

Cループ:343ミリ秒

ここで、C for ループのパフォーマンスが C# ループよりも優れていることを目的として上記のテストを開始しましたが、私の理解では正反対になり、この質問に同意して同意しました...しかし、for ループの上限範囲を増やすと、 CのパフォーマンスはC#と比較してうまくいきます...

今、私は、テストのアプローチが間違っているのか、それとも期待されるパフォーマンス結果なのかと考えています.

4

1 に答える 1

3

ここで起こっていることは、P/Invokeを使用してC関数を呼び出すという固定オーバーヘッドを無視しているということです。

C関数C#バージョンよりも高速ですが、呼び出しのオーバーヘッドが比較的大きいため、小さな配列の場合、呼び出しのオーバーヘッドが全体の時間の比較的大きな割合を占めるため、C関数は遅く見えるようになります。

ただし、コレクションのサイズを大きくすると、Cバージョンの余分な速度がそれ自体を表明し、実行速度が速くなるまで、オーバーヘッドは全体の時間に占める割合がますます小さくなります。

C#関数の時間を見ると、実際にNに比例して増加していることがわかります。これは、予想どおりです。Nを100倍に増やした後、T=4とT=418を比較します。期待どおりです。ただし、上記の理由により、C時間は直線的に増加するようには見えません。

ちなみに、少なくとも2つのタイミングを取る場合は、連立方程式を使用して次のことを解くことができます。

T = K + XN

ここで、Kは固定オーバーヘッド、Xは要素ごとのオーバーヘッドです。

アンマネージコードを呼び出すための固定オーバーヘッドは約5.6ミリ秒であり、要素あたりのオーバーヘッドは3.373737 x 10^-6ミリ秒であるとあなたのタイミングから計算しました。

そのオーバーヘッドはやや大きいように見えますが、測定データにはいくつかの不正確さがあります。

于 2013-02-19T09:18:56.450 に答える