為什么當我為它分配另一個陣列時,我的三維陣列變得如此緩慢?
SerializableQuaternion 是用于保存的自定義型別,因此它與 Quaternion 不同。
有沒有更好的方法來提高復制性能?
var anro = Quaternion[60,60,60]; //216000 element
Rotate = new SerializableQuaternion[anro.GetLength(0), anro.GetLength(1), anro.GetLength(2)];
if (anro != null)
{
for (int a = 0; a < anro.GetLength(0); a )
{
for (int b = 0; b < anro.GetLength(1); b )
{
for (int c = 0; c < anro.GetLength(2); c )
{
Rotate[a, b, c] = anro[a, b, c];
}
}
}
}
或者如何使 array.copy 可以復制不同的版本型別?
my custom type
[System.Serializable]
public struct SerializableQuaternion
{
public float x;
public float y;
public float z;
public float w;
public SerializableQuaternion(float rX, float rY, float rZ, float rW)
{
x = rX;
y = rY;
z = rZ;
w = rW;
}
public override string ToString()
{
return String.Format("[{0}, {1}, {2}, {3}]", x, y, z, w);
}
public static implicit operator Quaternion(SerializableQuaternion rValue)
{
return new Quaternion(rValue.x, rValue.y, rValue.z, rValue.w);
}
public static implicit operator SerializableQuaternion(Quaternion rValue)
{
return new SerializableQuaternion(rValue.x, rValue.y, rValue.z, rValue.w);
}
}
uj5u.com熱心網友回復:
剛剛經過測驗,11ms在我看來實際上并沒有那么慢 - 當然取決于你必須多久執行一次。
然而,
Array.Copy會很快,但主要問題是它Quaternion是SerializableQuaternion不同的型別,所以你不能使用它。您也不能使用
Buffer.BlockCopy,因為型別不是原始型別(float,int等)。
但你可以做的是使用Marhsal.Copy.
為此,您必須知道您的結構是如何以位元組為單位布局的,幸運的是,我們碰巧從源代碼中知道Quaternion
[StructLayout(LayoutKind.Sequential)] [Unity.IL2CPP.CompilerServices.Il2CppEagerStaticClassConstruction] public partial struct Quaternion : IEquatable<Quaternion>, IFormattable { // X component of the Quaternion. Don't modify this directly unless you know quaternions inside out. public float x; // Y component of the Quaternion. Don't modify this directly unless you know quaternions inside out. public float y; // Z component of the Quaternion. Don't modify this directly unless you know quaternions inside out. public float z; // W component of the Quaternion. Don't modify this directly unless you know quaternions inside out. public float w; ....
所以你只需要確保你的型別在位元組上看起來完全一樣(這似乎已經是這樣了)。
現在我不是元帥專家,所以甚至可能有一種更直接的方法來做到這一點,但你可以在轉換Quternion[,,]到byte[]和從那里到SerializableQuaternion[,,]喜歡的步驟之間有一個中間步驟
private static void MarshalCopy<TFrom, TTo>(TFrom[,,] source, TTo[,,] destination) where TFrom : struct where TTo : struct
{
if (Marshal.SizeOf(typeof(TFrom)) != Marshal.SizeOf(typeof(TTo)))
{
throw new InvalidOperationException($"{typeof(TFrom).AssemblyQualifiedName} can not by marshaled into {typeof(TTo).AssemblyQualifiedName}");
}
var sourceHandle = GCHandle.Alloc(source, GCHandleType.Pinned);
var destinationHandle = GCHandle.Alloc(destination, GCHandleType.Pinned);
try
{
var sourcePointer = sourceHandle.AddrOfPinnedObject();
var bytes = new byte[source.Length * Marshal.SizeOf(typeof(TFrom))];
Marshal.Copy(sourcePointer, bytes, 0, bytes.Length);
var destinationPointer = destinationHandle.AddrOfPinnedObject();
Marshal.Copy(bytes, 0, destinationPointer, bytes.Length);
}
finally
{
if (sourceHandle.IsAllocated)
sourceHandle.Free();
if (destinationHandle.IsAllocated)
destinationHandle.Free();
}
}
和一個小演示
var origin = new Quaternion[60, 60, 60];
for (var a = 0; a < origin.GetLength(0); a )
{
for (var b = 0; b < origin.GetLength(1); b )
{
for (var c = 0; c < origin.GetLength(2); c )
{
origin[a, b, c] = Quaternion.Euler(UnityEngine.Random.Range(-360f, 360f), UnityEngine.Random.Range(-360f, 360f), UnityEngine.Random.Range(-360f, 360f));
}
}
}
var target = new SerializableQuaternion[origin.GetLength(0), origin.GetLength(1), origin.GetLength(2)];
var sw = new Stopwatch();
sw.Restart();
for (var a = 0; a < origin.GetLength(0); a )
{
for (var b = 0; b < origin.GetLength(1); b )
{
for (var c = 0; c < origin.GetLength(2); c )
{
target[a, b, c] = origin[a, b, c];
}
}
}
sw.Stop();
UnityEngine.Debug.Log("Your way: " sw.ElapsedMilliseconds "ms");
sw.Restart();
var target2 = new SerializableQuaternion[origin.GetLength(0), origin.GetLength(1), origin.GetLength(2)];
MarshalCopy(origin, target2);
sw.Stop();
UnityEngine.Debug.Log("Alternative way: " sw.ElapsedMilliseconds "ms");
for (var a = 0; a < origin.GetLength(0); a )
{
for (var b = 0; b < origin.GetLength(1); b )
{
for (var c = 0; c < origin.GetLength(2); c )
{
if ((Quaternion)target2[a, b, c] != target[a, b, c])
{
UnityEngine.Debug.LogError("Oh no error in copy!");
}
}
}
}
=>
Your way: 12ms
Alternative way: 1ms
并從另一個測驗運行600, 60, 60
Your way: 123ms
Alternative way: 12ms
所以我認為我們可以說我的速度更快10;)
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/508672.html
