編集: C# コードの追加unsafe
バージョン。この提案に感謝しますunsafe
。C# コードはより高速に実行されますが、約 3% しかありません。
短いバージョン: C# と Objective-C でいくつかのベンチマーク コードを作成し、iPad 3 でテストしました。これが私の質問です。ベンチマークに使用したコード (以下を参照) よりも高速に実行される C# コードを記述できますか? それとも、MonoTouch/Obj-C 固有の違いが原因でしょうか?
長いバージョン:計画中のマルチプラットフォーム ゲームの小さなプロトタイプを書きました。ゲーム コアを Windows/.NET から iPad 3/MonoTouch に移植した後、iPad でのコードの実行速度が非常に遅いことに気付きました。ゲーム コアの特定の重要な部分は、Intel CPU よりも iPad CPU の方が約 10 倍遅く実行されました (iPad は ARM プロセッサで実行されるため、これは正常なようです)。
ただし、これは私たちのゲームにとって大きな問題であるため、iPad 3 で小さなベンチマーク テストを実行しました。ベンチマークは、多くの単純な追加と配列の検索を行います。MonoTouch は GC で処理されているため、Obj-C を支持する小さな違いが見られると予想していましたが、驚いたことに、MonoTouch コードは Obj-C コードよりも実行に多くの時間を必要としました。正確には:float
float
- DEBUG モードとRELEASE モードで実行する必要があるObj-Cコード。
47'647 ms
27'162 ms
- DEBUG モードおよびRELEASE モードでの実行に必要なポインターを使用しないMonoTouchコード。
unsafe
116'885 ms
40'002 ms
- DEBUG モードおよびRELEASE モードで実行するために必要なポインターを含むMonoTouchコード。
unsafe
90'372 ms
38'764 ms
もちろん、気になるのはRELEASEモード。
LLVM
MonoTouchが Obj-Cと同じネイティブ コードにコンパイルされるという事実を考えると、この違いは私には少し大きいように思えます。
私が使用した Obj-C コードは次のとおりです。
int i, j;
long time = GetTimeMs64();
float * arr = (float *) malloc(10000 * sizeof(float)); // 10'000
for (j = 0; j < 100000; j++) { // 100'000
arr[0] = 0;
arr[1] = 1;
for (i = 2; i < 10000; i++) { // 10'000
arr[i] = arr[i - 2] + arr[i - 1];
if (arr[i] > 2000000000) { // prevent arithm. overflow
arr[i - 1] = 0;
arr[i] = 1;
}
}
}
long time2 = GetTimeMs64() - time;
GetTimeMs64()
<sys/time.h>
のを使用しgettimeofday
ます。
ここに私のC#/MonoTouchコードのunsafe
バージョンがあります:
var array = new float[10000]; // 10'000
var watch = System.Diagnostics.Stopwatch.StartNew();
fixed (float* arr = array)
{
for (int j = 0; j < 100000; j++) // 100'000
{
*(arr + 0) = 0;
*(arr + 1) = 1;
for (int i = 2; i < 10000; i++) // 10'000
{
*(arr + i) = *(arr + i - 2) + *(arr + i - 1);
if (*(arr + i) > 2000000000) // prevent arithm. overflow
{
*(arr + i - 1) = 0;
*(arr + i) = 1;
}
}
}
}
watch.Stop();
編集 2:これは、Xamarin から得た回答です。
この特定の例には、モノのパフォーマンスを損なう 2 つの問題があります。
まず、LLVM ではなくデフォルトの MonoTouch コンパイラを使用している場合、実行速度ではなくコンパイル速度が調整されているため、パフォーマンスが低下することが予想されます。LLVM を使用すると、より良い結果が得られます。
次に、mono は浮動小数点に関する ECMA 仕様に準拠し、すべての計算を倍精度で行います。float を使用する C コードと比較すると、これは通常、特に測定可能なパフォーマンス コストを伴います。
正確性を損なうことなく倍精度のパフォーマンスを緩和する方法、または少なくともオプトイン メカニズムを使用する方法を検討してきました。