2015年7月27日月曜日

C# 多次元配列の初期化,ゼロクリア速度の比較

多次元配列を初期化(ゼロクリア)するのにかかる処理時間を計測した。
厳密には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 件のコメント:

コメントを投稿