1

私は非常に頻繁に呼ばれる機能を持っています。この関数には、内部に2つのネストされたforループがあります。各forループは0から900まで繰り返されます。コードは次のようになります。

 for (int j = 0; j < width; j++)
            {
                for (int k = 0; k < height; k++)
                {
                    switch (Dim2[j * width + k])
                    {
                        case 0:
                            cwA = Dim0[j * width + ((k == (height - 1)) ? 0 : (k + 1))];
                            ccwA = Dim0[((j == (width - 1)) ? 0 : (j + 1)) * width + k];
                            oppA = Dim0[((j == (width - 1)) ? 0 : (j + 1)) * width + ((k == (height - 1)) ? 0 : (k + 1))];
                            cwB = Dim3[j * width + ((k == (height - 1)) ? 0 : (k + 1))];
                            ccwB = Dim3[((j == (width - 1)) ? 0 : (j + 1)) * width + k];
                            oppB = Dim3[((j == (width - 1)) ? 0 : (j + 1)) * width + ((k == (height - 1)) ? 0 : (k + 1))];
                            break;

                        case 1:
                            cwA = Dim0[((j == (width - 1)) ? 0 : (j + 1)) * width + k];
                            ccwA = Dim0[j * width + ((k == 0) ? (height - 1) : (k - 1))];
                            oppA = Dim0[((j == (width - 1)) ? 0 : (j + 1)) * width + ((k == 0) ? (height - 1) : (k - 1))];
                            cwB = Dim3[((j == (width - 1)) ? 0 : (j + 1)) * width + k];
                            ccwB = Dim3[j * width + ((k == 0) ? (height - 1) : (k - 1))];
                            oppB = Dim3[((j == (width - 1)) ? 0 : (j + 1)) * width + ((k == 0) ? (height - 1) : (k - 1))];
                            break;

                        case 2:
                            cwA = Dim0[((j == 0) ? (width - 1) : (j - 1)) * width + k];
                            ccwA = Dim0[j * width + ((k == (height - 1)) ? 0 : (k + 1))];
                            oppA = Dim0[((j == 0) ? (width - 1) : (j - 1)) * width + ((k == (height - 1)) ? 0 : (k + 1))];
                            cwB = Dim3[((j == 0) ? (width - 1) : (j - 1)) * width + k];
                            ccwB = Dim3[j * width + ((k == (height - 1)) ? 0 : (k + 1))];
                            oppB = Dim3[((j == 0) ? (width - 1) : (j - 1)) * width + ((k == (height - 1)) ? 0 : (k + 1))];
                            break;

                        case 3:
                            cwA = Dim0[j * width + ((k == 0) ? (height - 1) : (k - 1))];
                            ccwA = Dim0[((j == 0) ? (width - 1) : (j - 1)) * width + k];
                            oppA = Dim0[((j == 0) ? (width - 1) : (j - 1)) * width + ((k == 0) ? (height - 1) : (k - 1))];
                            cwB = Dim3[j * width + ((k == 0) ? (height - 1) : (k - 1))];
                            ccwB = Dim3[((j == 0) ? (width - 1) : (j - 1)) * width + k];
                            oppB = Dim3[((j == 0) ? (width - 1) : (j - 1)) * width + ((k == 0) ? (height - 1) : (k - 1))];
                            break;
                    }
                    woll = (((oppB + ccwB) + cwB) + Dim3[j * width + k]) > 0;
                    collision = ((Dim0[j * width + k] == oppA) && (cwA == ccwA)) && (Dim0[j * width + k] != cwA);
                    Dim6[j * width + k] = (short)(3 - Dim2[j * width + k]);
                    if (woll || collision)
                    {
                        Dim4[j * width + k] = Dim0[j * width + k];
                    }
                    else
                    {
                        Dim4[j * width + k] = _phase ? cwA : ccwA;
                    }
                }
            }

これらのforループの実行には約0.1秒かかりますが、これは遅すぎます。2次元配列を1次元配列に置き換えました。これにより、パフォーマンスが大幅に向上しました。コードの他のパフォーマンスの改善はありますか?C ++に移行した場合、より速く動作しますか?配列の操作に他の言語を使用する必要がありますか?あなたは何を提案しますか?
よろしくお願いします、
サム

4

7 に答える 7

2

、、、などを変数にリファクタリングしてheight - 1、1回だけ計算されるようにします。それは少し役立ちます。実際、このリストに追加することができます:j + 1width - 1j * width

(j == (width - 1)) ? 0 : (j + 1)
于 2012-05-21T15:59:08.833 に答える
1

このプロジェクトで安全でないコンテキストを使用できますか?配列から読み取るたびに.Netの配列境界チェックなどが発生しなくなるため、配列にインデックスを付けるのではなく、ポインタを使用することでパフォーマンスを大幅に向上させることができるはずです。

于 2012-05-21T15:59:11.497 に答える
1

C ++に移行した場合、より速く動作しますか?

C ++でネイティブを参照する場合は、そうする必要があります。
理由
1.ガベージコレクターがない
2.メモリの再調整がない
3.CLRがない

ただし、CLRによるマネージコードには最適化が含まれている場合がありますが、同等のネイティブコードの方が高速です。これが、BCL CPUを集中的に使用するロジックのほとんどがネイティブコード(MethodImplOptions .InternalCallで装飾されている)にある正確な理由です。

于 2012-05-21T15:59:47.143 に答える
0

私はC#の専門家ではありませんが、「静的」でループの内側(インライン条件と乗算)のすべての計算をループの外側に配置しようとします。

于 2012-05-21T15:59:49.717 に答える
0

大幅な高速化が必要な場合は、少なくとも外側のループでは、複数のスレッドの使用を検討する必要があります。また、オーバーフローチェックを使用していないことを確認してください。

于 2012-05-21T16:07:03.737 に答える
0

別の解決策は、特に複数のコアを備えた最新のコンピューターの場合、外側のforループをParallel.Forの呼び出しに変更することです。

ただし、最初にここで提案されている他の最適化を行う必要があります。

于 2012-05-21T16:18:51.370 に答える
0

内側のループを3つコピーすることで、完全に削除j == 0してテストできます。ループから最初と最後の反復を切り離すと、j == (width - 1)同じことを行うことができます。kもちろん、両方を行うと、内部コードのコピーが9つあることになりますが、これはあまり良いことではありません。特にお勧めしません。条件に応じて条件を削除するkと、より大きな効果が得られるはずです。また、移動できるためです。jとにかく内側のループの外側に依存する条件。

于 2012-05-21T16:22:50.853 に答える