[英]How to improve a select query performance?
我正在研究一種方法,該方法基本上將顏色數組(Unity 類型)作為參數,並將列表中包含的所有顏色替換為另一個顏色數組中包含的另一種顏色。 例如,您有 3 種蒙版顏色(紅色、藍綠色),因此每個綠色像素將被紋理 1 替換,每個紅色像素將被紋理 2 替換,等等...
我以前的方法很混亂,有很多 if 循環,並且需要大約 1.6 毫秒才能執行,我認為這真的很糟糕。
最后我想出了另一種使用 LINQ 的方法,它更干凈,但令人驚訝的是,這個查詢實際上需要超過 4.5 毫秒才能執行(對於 64x64 數組):
Color[] newTexture = texture.GetPixels()
.Select((color, index) => masks.Contains(color) ? textures[Array.IndexOf(masks, color)][index] : color)
.ToArray();
我嘗試了並行化,但更糟糕的是:
Color[] newTexture = texture.GetPixels().AsParallel()
.Select((p, i) => masks.Contains(p) ? textures[Array.IndexOf(masks, p)][i] : p)
.ToArray();
你知道為什么這個查詢需要這么多時間以及我如何改進它嗎?
非常感謝您的幫助。
LINQ 的不幸事實是它幾乎永遠不會比 for 循環快。 這是因為不像 C++ 和 Rust 這樣可以內聯/編譯 lambda 表達式的語言,任何時候調用Action
對象,或在IEnumerable<T>
等上調用MoveNext()
時,都會有一個VTable 查找。 因此,您不應該將它真正用於游戲,至少在性能很重要的地方不應該。
除了 LINQ 遭受的固有性能問題之外,您還不必要地復制像素的副本,並且您正在查看掩碼數組兩次。
你提到你的 for 循環很亂? 像這樣的東西會更好嗎?
// GetPixels() already gives you a copy, no need to copy it again
Color[] newTexture = texture.GetPixels();
// Microsoft's compilers make better code for spans than for arrays,
// maybe Mono does too?
Span<Color> textureSpan = newTexture;
Span<Color> maskSpan = masks;
for (int i = 0; i < textureSpan.Length; i++)
{
// by checking if the index returned from IndexOf is not negative,
// you can omit Contains()
int maskIndex = maskSpan.IndexOf(textureSpan[i]);
// only change the pixels that need to be changed
if(maskIndex >= 0)
{
textureSpan[i] = textures[maskIndex][i];
}
}
return newTexture;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.