[英]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.