Vector3.magnitudeの負荷について
きっかけ
とある実装でC#処理負荷が非常に高く困っていたのですが、C#の実行速度が遅いからと考えていました。
ふと、magnitudeの平方根計算が非常に高負荷になっているのではないかと思い、検証してみました。
A,B2点間の距離を出す式は以下のようになり、公式リファレンスにも負荷があるよと記述があります
HatenaってTex記述もできるんだねすごぃ
Unity - Scripting API: Vector3.sqrMagnitude
計測方法
そこで負荷を以下の計算式で試してみました
| magnitude | Vector3.magnitude |
| sqrMagnitude | Vector3.sqrMagnitude |
| systemMagnitude | System.Math.Sqrt(V.x*V.x+V.y*V.y+V.z*V.z) |
| systemSqrMagnitude | V.x*V.x+V.y*V.y+V.z*V.z |
最初に以下のようなスクリプトを組んだのですが、ラムダ式の負荷が想像以上に高く(ベタに記述した場合の2倍以上)正確な実行速度差が分からなかったためdelegateを使わないようにしています。
また、実行結果が正しい事を確認するために結果をlengthとして出力しています。
IEnumerator Start () {
yield return new WaitForSeconds(0.5f);
CalcTest("magnitude", (v) => v.magnitude);
yield return 0;
CalcTest("sqrMagnitude", (v) => v.sqrMagnitude);
yield return 0;
CalcTest("systemMagnitude", (v) => (float)System.Math.Sqrt(v.x * v.x + v.y * v.y + v.z * v.z));
yield return 0;
CalcTest("systemSqrMagnitude", (v) => v.x * v.x + v.y * v.y + v.z * v.z);
}
void CalcTest(string n, System.Func<Vector3,float> method) {
var vA = Vector3.zero;
var vB = new Vector3(2f, 2f, 2f);
var v = vA - vB;
float length = 0f;
float time = Time.realtimeSinceStartup;
for(int i = 0; i < COUNT; i++) {
length = method(v);
}
Debug.Log(n + "->" + (Time.realtimeSinceStartup - time) + " length=" + length);
}
実行結果
今回は10000000回の実行速度を計測します。
環境
- Corei7-2600K 3.4Ghz
- UnityEditor
magnitude->2.611315 length=3.464102
sqrMagnitude->1.627022 length=12
systemMagnitude->1.290134 length=3.464102
systemSqrMagnitude->0.8662863 length=12
まさかの結果でした。
magnitudeはSystem.Mathの2倍の負荷がかかる事がわかりました。
magnitudeの実装を見るとSystem.Math.Sqrtを実行しているだけだったのでVector3のプロパティを通すだけで負荷がかかるようです。
平方根の負荷自体は1.5倍程度だったので激しくボトルネックになることはなさそうです。
面白い結果が分かってよかったです。