編輯:增加了unsafe
版本的C#代碼。謝謝你們的建議,unsafe
C#代碼運行得更快,但只有大約3%。ObjC與MonoTouch浮點和陣列性能
短版:我在C#和Objective-C中寫了一些基準測試代碼和測試它在iPad 3,50%-150%的時間比執行之間所需的MonoTouch的/ C#版本Objective-C中的相同代碼。這裏是我的問題:我可以編寫比我用於基準測試的代碼執行速度更快的C#代碼(見下文),還是由於某些固有的MonoTouch/Obj-C差異導致?
龍版本:我只是寫了一個小原型計劃的多平臺遊戲。將遊戲內核從Windows/.NET移植到iPad 3/MonoTouch後,我注意到代碼在iPad上運行速度較慢。遊戲內核的某些關鍵部分在iPad CPU上運行速度比在Intel CPU上慢10倍左右(這似乎是正常現象,因爲iPad是使用ARM處理器運行的)。
然而,因爲這是我們的遊戲的一個主要問題,我經營的小基準測試在iPad 3,一旦MonoTouch的,然後用普通Objective-C的同樣的事情。該基準測試增加了很多簡單的float
和float
陣列查找。由於MonoTouch已經GC了,我預計會看到Obj-C的小小差異,但讓我驚訝的是,MonoTouch代碼比Obj-C代碼需要更多的時間來運行。更確切地說:
- 的的OBJ-C代碼所需
47'647 ms
在調試模式下運行,並且在釋放模式27'162 ms
。 - MonoTouch沒有使用
unsafe
代碼的指針需要116'885 ms
在DEBUG模式下運行,而40'002 ms
在RELEASE模式下運行。 - 的MonoTouch的代碼與需要
90'372 ms
在調試模式下運行unsafe
指針,並在釋放模式38'764 ms
。
當然,RELEASE模式是我所關心的。
鑑於MonoTouch編譯爲與Obj-C相同的本地LLVM
代碼,這一差異對我來說似乎有點高。
這裏是的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得到了答案:
有兩個問題與此特定損害單聲道性能的例子。首先,如果您使用的是默認MonoTouch編譯器,而不是LLVM,則可能會導致性能降低,因爲它的編譯速度爲 ,而不是執行速度。 LLVM會給你更好的結果。其次,單聲道符合關於浮點的ECMA規範,並且 以雙精度進行所有計算。如果與使用 浮點數的C代碼相比,這通常會具有可測量的性能成本。
我們一直在尋找各種方法來放鬆雙精度性能 而不影響正確性,或者至少有一個選擇在 機制。
單點觸摸是否允許「不安全」?你可以用'float *'做所有這些 - 應該明顯更快......? –
謝謝,不幸的是它只有3%的速度。 – cheeesus
@cheeesus你最終決定使用什麼? – Den