読者です 読者をやめる 読者になる 読者になる

CosやSinをテーブル引きにする効果

      • -

追記 2017/2/8 23:20

各所からツッコミを受けました。
テーブル引きの恩恵を受けるようなコードは、現在の実践環境ではあまりなく、普通に関数を使ったほうが有利というのが説が多いです。
以下のテストはキャッシュが効きやすい状態のテストなので一応、テーブル引きが勝っていますが、結構特殊な状況です。
ほんとうは、ちゃんと実際のゲーム中で計測するべきなんですけど、すいませんm(_ _)m

速度的なメリットは怪しいけどテーブル引きのメリットは、
通信量を落とせるとか(角度をfloatの32bitじゃなく8bitとか16bitで持ちたいとき)
値が実行環境に依存しないとか
というメリットがあると言われ、自分も納得しました。

      • -


CosやSinをテーブル引きにする効果

ゲーム制作において、高速化のためにCosやSinといった関数をテーブル引きにするというのは、よくある話である。

自分のゲーム制作環境でも少しでも処理を軽くするためにテーブル引きSin,Cosを作ってみようかと思ったのだけれど、そもそもどれぐらい処理の高速化が見込めるのか、Unity上で試してみた。

github.com

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TestScript : MonoBehaviour {
    public int loopCount = 10000000;
    System.Diagnostics.Stopwatch stopWatch = new System.Diagnostics.Stopwatch();

    public int tableSize = 360;
    public const float PI2 = Mathf.PI * 2.0f;
    float[] cosTable;

	void Start () {
        cosTable = new float[ tableSize ];
        for( int i = 0; i < tableSize; ++i )
        {
            float theta = (float)i / tableSize * PI2;
            cosTable[i] = Mathf.Cos( theta );
        }
    }

    [ContextMenu("Test Mathf")]
	void TestMathf () {
        stopWatch.Reset();
        stopWatch.Start();
        float sum = 0.0f;
        for( int i = 0; i < loopCount; ++i )
        {
            sum += Mathf.Cos( (float)i );
        }
		
        stopWatch.Stop();
        Debug.Log( "time : " + stopWatch.Elapsed + " sum, " + sum );
	}

    [ContextMenu("Test Cos Table")]
	void TestCosTable () {
        stopWatch.Reset();
        stopWatch.Start();
        float sum = 0.0f;
        for( int i = 0; i < loopCount; ++i )
        {
            sum += getCosFromTable( (float)i );
        }
        stopWatch.Stop();
        Debug.Log( "time : " + stopWatch.Elapsed + " sum, " + sum );
	}

	int getCosTableIndex ( float theta ) {
        return (int)( theta / PI2 * tableSize ) % tableSize;
    }

	float getCosFromTable ( float theta ) {
        int index = getCosTableIndex( theta );
        return cosTable[ index ];
    }
}


1000万回、Cosを計算して加算した結果、自分のMacbook Pro上で、Mathf.Cosは0.552秒、tableを使ったCosは0.453秒とTableを使ったほうが20%ぐらい高速だった。

もっと差が出るかと思っていたのだけど、そうでもなかった。

tableを使った方は精度がイマイチなのでご利用は計画的に。