先说结果,在不使用Job做优化的前提下,Mathematics数学库着实惊到我了,矩阵乘法快了近十倍
1.测试结果
下图的测试数据是在2019.3.6环境下,模拟100万次4x4矩阵运算得出的,后面两个使用了job进行了优化,可以看到,新数学库的float4x4在不使用jobsystem的情况下就可以达到和Matrix4x4使用jobsystem计算时相当的速度。Mathematics使用了SIMD并行计算,有兴趣可以自行查阅。
这里仅仅只测试了4x4矩阵在进行乘法运算的情况,不代表在实际使用中也可以达到这样的效率。
2.测试用例
使用Package Manager安装数学库Mathematics。注意Jobs是集成在unity中的,不需要额外安装,Package Manager里的Jobs是提供了一些额外的Job类型。
下面的代码放入unity后可以直接运行看结果。
using System;
using Unity.Collections;
using Unity.Jobs;
using Unity.Mathematics;
using UnityEngine;
public class Test : MonoBehaviour
{
public int count = 100000;
void Start()
{
Debug.Log("Matrix4x4: " + DebugActionRunTime(() =>
{
for (int i = 0; i < count; i++)
{
Matrix4x4 aa = new Matrix4x4();
Matrix4x4 bb = new Matrix4x4();
Matrix4x4 result = aa * bb;
}
}) + "ms");
Debug.Log("float4x4: " + DebugActionRunTime(() =>
{
for (int i = 0; i < count; i++)
{
float4x4 aa = new float4x4();
float4x4 bb = new float4x4();
float4x4 result = aa * bb;
}
}) + "ms");
Debug.Log("Matrix4x4 Job: " + DebugActionRunTime(() =>
{
NativeArray<Matrix4x4> aa = new NativeArray<Matrix4x4>(count, Allocator.TempJob);
NativeArray<Matrix4x4> bb = new NativeArray<Matrix4x4>(count, Allocator.TempJob);
NativeArray<Matrix4x4> results = new NativeArray<Matrix4x4>(count, Allocator.TempJob);
Matrix4x4Mul matrix4X4 = new Matrix4x4Mul();
matrix4X4.aa = aa;
matrix4X4.bb = aa;
matrix4X4.results = results;
matrix4X4.Schedule(results.Length, 5).Complete();
aa.Dispose();
bb.Dispose();
results.Dispose();
}) + "ms");
Debug.Log("float4x4 Job: " + DebugActionRunTime(() =>
{
NativeArray<float4x4> aa = new NativeArray<float4x4>(count, Allocator.TempJob);
NativeArray<float4x4> bb = new NativeArray<float4x4>(count, Allocator.TempJob);
NativeArray<float4x4> results = new NativeArray<float4x4>(count, Allocator.TempJob);
float4x4Mul matrix4X4 = new float4x4Mul();
matrix4X4.aa = aa;
matrix4X4.bb = aa;
matrix4X4.results = results;
matrix4X4.Schedule(results.Length, 5).Complete();
aa.Dispose();
bb.Dispose();
results.Dispose();
}) + "ms");
}
/// <summary>
/// 执行一个方法并返回它的执行时间
/// </summary>
/// <param name="action"></param>
/// <returns></returns>
public static float DebugActionRunTime(Action action)
{
float time = DateTime.Now.Millisecond + DateTime.Now.Second * 1000;
action();
return DateTime.Now.Millisecond + DateTime.Now.Second * 1000 - time;
}
public struct float4x4Mul : IJobParallelFor
{
[ReadOnly] public NativeArray<float4x4> aa;
[ReadOnly] public NativeArray<float4x4> bb;
public NativeArray<float4x4> results;
public void Execute(int index)
{
results[index] = bb[index] * results[index];
}
}
public struct Matrix4x4Mul : IJobParallelFor
{
[ReadOnly] public NativeArray<Matrix4x4> aa;
[ReadOnly] public NativeArray<Matrix4x4> bb;
public NativeArray<Matrix4x4> results;
public void Execute(int index)
{
results[index] = bb[index] * results[index];
}
}
}