我正在研究一種方法,該方法基本上將顏色陣列(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();
你知道為什么這個查詢需要這么多時間以及我如何改進它嗎?
非常感謝您的幫助。
uj5u.com熱心網友回復:
LINQ 的不幸事實是它幾乎永遠不會比 for 回圈快。這是因為不像 C 和 Rust 這樣的 lambda 運算式可以被行內/編譯掉的語言,任何時候你呼叫一個Action物件,或者呼叫MoveNext()等等IEnumerable<T>,都有一個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;
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/497404.html
上一篇:結合兩個模型,僅檢索a.firstname、a.lastname、b.name并作為串列回傳以使用linq在mvc視圖中填充
