厳密にはUnityの話ではないのだろうけど、Unity上で行った。
方法
〇 変数は、float型で配列長100x100x100 の3次元配列を以下のように宣言した。
float[,,] hoge = new float[100, 100, 100];
〇 計測方法は、以下3通りの方法をそれぞれ100回実行するのにかかった時間を計測した。
方法1. new演算子
hoge = new float[100, 100, 100];
方法2. Array.Clear()
System.Array.Clear(hoge, 0, hoge.Length);
方法3. forループ
unsafe
{
fixed (float* p = &hoge[0, 0, 0])
{
float* pp = p;
for (int i = 0; i < hoge.Length; i++)
*pp++ = 0f;
}
}
結果
計測1回目 | 計測2回目 | 計測3回目 | 計測4回目 | 計測5回目 | |
---|---|---|---|---|---|
new演算子 | 0.1674882 | 0.1622308 | 0.2898813 | 0.1600189 | 0.1693485 |
Array.Clear() | 0.02281523 | 0.02285552 | 0.02873182 | 0.02298915 | 0.02374685 |
forループ | 0.507967 | 0.4435526 | 0.522768 | 0.4373467 | 0.5145774 |
以上の結果から、
多次元配列を最も速く初期化できる方法はArray.Clear()であることがわかった。
forループでは1回あたり5ms、
ということは60fpsにおける1フレーム(16.66...ms)の1/3に相当する時間がかかるわけか。
…そもそもnewを初期化扱いしていいのかな?
コード
作成したコードはこちらusing UnityEngine;
using System.Collections;
public class ZeroClearTest : MonoBehaviour {
float[, ,] hoge = new float[100,100,100];
void Start () {
float time = Time.realtimeSinceStartup;
for (int i = 0; i < 100; i++)
Clear1();
Debug.Log("Clear1 : " + (Time.realtimeSinceStartup - time).ToString());
time = Time.realtimeSinceStartup;
for (int i = 0; i < 100; i++)
Clear2();
Debug.Log("Clear2 : " + (Time.realtimeSinceStartup - time).ToString());
time = Time.realtimeSinceStartup;
for (int i = 0; i < 100; i++)
Clear3();
Debug.Log("Clear3 : " + (Time.realtimeSinceStartup - time).ToString());
}
void Clear1()
{
hoge = new float[100, 100, 100];
}
void Clear2()
{
System.Array.Clear(hoge, 0, hoge.Length);
}
void Clear3()
{
unsafe
{
fixed (float* p = &hoge[0, 0, 0])
{
float* pp = p;
for (int i = 0; i < hoge.Length; i++)
*pp++ = 0f;
}
}
}
}
最後に、参考サイト
http://smdn.jp/programming/netfx/arrays/2_operations/
https://social.msdn.microsoft.com/Forums/ja-JP/307450c2-bdfe-497e-b93d-e4b8b9f71d49/c?forum=csharpgeneralja
unsafeコードの動かし方はこちら
http://unitymemonote.blogspot.jp/2015/07/unity-unsafe.html
0 件のコメント:
コメントを投稿