假设我有以下代码
public static class Main
{
public struct Vec3
{
public float x, y, z;
}
public void Entry()
{
float[9] floats = new floats[9] { 1f, 2f, 3f, 4f, 5f, 6f, 7f, 8f, 9f };
Vec3[3] vecs;
}
}
我想将float []转换为Vec3 []。
有没有办法用Marshaling执行此操作,以便所需的复制比迭代float []并将每个浮点数复制到Vec3 []更快?假设float []非常大。
答案 0 :(得分:1)
您可以使用System.Runtime.InteropServices.Marshal
类来执行此操作:
unsafe
{
fixed (Vec3* vecsPointer = vecs)
{
Marshal.Copy(floats, 0, new IntPtr(vecsPointer), floats.Length);
}
}
尽管如此,我认为如果可能的话,最好避免使用unsafe
,即使有一些可衡量的性能差异。对于我来说,选择上述内容直接管理副本(在发布版本中可能非常快,但可能没有上述速度快),这必须是一个相当显着的性能提升。
当然,您应该仔细衡量每种方法的总体影响,并确保在采用unsafe
方法之前值得进行潜在的维护麻烦。
编辑:出于好奇,我继续做了一个简单的测试。我创建了一个float[]
1MB的大小并复制到Vec3[]
。我使用了上面的内容,并将其与一个看似如下的简单循环进行比较:
for (int k = 0, l = 0; k + 2 < floats.Length; k += 3, l++)
{
vecs[l].x = floats[k];
vecs[l].y = floats[k + 1];
vecs[l].z = floats[k + 2];
}
在我的测试中,我每次试用每次执行10,000次,副本的总大小约为10GB。
unsafe
版本“仅”比安全版本快2倍(比慢)。每10,000次复印试用unsafe
约需1.5秒,安全时间约为3秒。 2倍的加速听起来相当不错,但当然,如果您的程序没有其他任何操作,那么您只能得到它。在一个真实世界的程序中,可能会转化为5%或更低的改进,具体取决于正在发生的其他事情。
我看到的其他一些有趣的事情:
unsafe
代码的设置开销将其保留,并且它与安全版本一样慢。