6
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

SinとかSqrt等の算術演算と掛け算の処理負荷を比べてみたを検証してみた

Last updated at Posted at 2019-02-21

前置き

この記事は以下の記事について独自検証をしたものです

「SinとかSqrt等の算術演算と掛け算の処理負荷を比べてみた」
https://qiita.com/geekdrums/items/1a6e7480f23c9ffbcfc0

マサカリウェルカムな元記事作者さんに感謝を

結論

元記事のコードはたぶん最適化でいろいろ消し飛んでる

こちらで計測した結果:

Mult Sin Sqrt Atan Exp Pow Pow2
1倍 24.39倍 1.20倍 35.23倍 23.58倍 41.82倍 31.84倍

Windows10でC#コンソールアプリで計測、C#のMath関数を利用、コードは記事最下部

動機

さすがにSqrtがMultより早いのはおかしくない?

デコンパイルしてみた

世の中にはC#バイナリをソースコードに戻してくれるソフトがある
その1つILSpyにかけてみることにする

結果

image.png

はい

対策

C#の最適化対策はよくわからないので
とりあえず結果が使われるかもしれないとコンパイラを疑心暗鬼に陥らせてみる

image.png

全ての計算がfの最終値に影響するようにしたのと
fをpublicメンバに代入した

でILSpy

image.png

いけてそう

他にもildasmで関数呼び出し自体が消えていないかとかも見たけど成果なかったので省略

追記

Q:sqrtは掛け算割り算なしで行けるから早くても普通では?
A:さすがに掛け算1回よりは遅いでしょ

Q:Mult以外は前の計算結果使ってないぞ!最適化されてるんじゃないのか!
A:使わなくても問題ないコード吐かれたからそうしてる

Sinのデコンパイル結果

image.png

ついでに機械語レイヤー

image.png

ちゃんとfsin命令込みでループしているのがわかる
(0x01580CC1にfsin命令があり、ループのjmp先はそれよりも前の0x01580CBF、ステップ実行でも確認済み)

最終的な実行結果

image.png

実行回数と実行にかかった時間をミリ秒単位で出力しただけ

具体的に何倍速かもう1回貼っときますね

Mult Sin Sqrt Atan Exp Pow Pow2
1倍 24.39倍 1.20倍 35.23倍 23.58倍 41.82倍 31.84倍

おわりに

unityは多分計測結果に関係ないだろうという慢心の元外した

IL弄ってfへ代入も排除した厳密計測したかったけどC#力が足らない

記事ももっと見栄えよくしたかったけどqiita力が足らない

自分はC#あまり書かないのでミスあるだろうけど、見つけた人はこの記事みたいに検証記事かいて、どうぞ

最後に検証に使ったコード置いときます

MathTest.cs
using System;
using System.Linq;

public class MathTest {
   public double count;
   public double step = 1;

   public MathTest(double count = 1000.0) {
         this.count = count;
   }

   public double trash;
   private void Mult() {
      double f = 1.0;

      for (double i = 0; i < count; i += step) {
         f = f * i;
      }
      trash = f;
   }

   private void Sin() {
      double f = 1.0;

      for (double i = 0; i < count; i += step) {
         f = Math.Sin(i);
      }
      trash = f;
   }

   private void Sqrt() {
      double f = 1.0;

      for (double i = 0; i < count; i += step) {
         f = Math.Sqrt(i);
      }
      trash = f;
   }

   private void Pow() {
      double f = 1.0;

      for (double i = 0; i < count; i += step) {
         f = Math.Pow(i, i);
      }
      trash = f;
   }

   private void Pow2() {
      double f = 1.0;

      for (double i = 0; i < count; i += step) {
         f = Math.Pow(i, 2);
      }
      trash = f;
   }

   private void Atan() {
      double f = 1.0;

      for (double i = 0; i < count; i += step) {
         f = Math.Atan(i);
      }
      trash = f;
   }

   private void Exp() {
      double f = 1.0;

      for (double i = 0; i < count; i += step) {
         f = Math.Exp(i);
      }
      trash = f;
   }

   public long[] run() {
      return new Action[] { Mult, Sin, Sqrt, Atan, Exp, Pow, Pow2 }.Select(act => {
         var sw = new System.Diagnostics.Stopwatch();
         sw.Start();
         act();
         sw.Stop();
         return sw.ElapsedMilliseconds;
      }).ToArray();
   }
}

class Program {
   static void Main(string[] args) {
      new MathTest(100.0).run(); // メモリキャッシュとか対策にちょっと回す
      Console.WriteLine("計測開始(単位はms)");
      Console.WriteLine("Mult, Sin, Sqrt, Atan, Exp, Pow, Pow2");
      foreach (double count in new double[] { 100_000.0, 1_000_000.0, 10_000_000.0, 100_000_000.0 }) {
         Console.WriteLine((int)count);
         Console.WriteLine(String.Join(", ", new MathTest(count).run()));
      }
      Console.ReadLine();
   }
}
6
1
17

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?