Ответы с форумов MSDN

Производительность Math.Pow

Date: 23.03.2017 3:21:45

Visual Studio 2012, оптимизация включена: вычисляется 2 раза

private void Form1_Paint(object sender, PaintEventArgs e)
{
    e.Graphics.DrawLine(Pens.Black, 0, this.captionTextHeight + this.captionLineWidth / 2, this.Width, this.captionTextHeight + this.captionLineWidth / 2);
}

// Code size       67 (0x43)
  .maxstack  8
  IL_0000:  ldarg.2
  IL_0001:  callvirt   instance class [System.Drawing]System.Drawing.Graphics [System.Windows.Forms]System.Windows.Forms.PaintEventArgs::get_Graphics()
  IL_0006:  call       class [System.Drawing]System.Drawing.Pen [System.Drawing]System.Drawing.Pens::get_Black()
  IL_000b:  ldc.r4     0.0
  IL_0010:  ldarg.0
  IL_0011:  ldfld      float32 WindowsFormsApplication1.Form1::captionTextHeight
  IL_0016:  ldarg.0
  IL_0017:  ldfld      float32 WindowsFormsApplication1.Form1::captionLineWidth
  IL_001c:  ldc.r4     2.
  IL_0021:  div
  IL_0022:  add
  IL_0023:  ldarg.0
  IL_0024:  call       instance int32 [System.Windows.Forms]System.Windows.Forms.Control::get_Width()
  IL_0029:  conv.r4
  IL_002a:  ldarg.0
  IL_002b:  ldfld      float32 WindowsFormsApplication1.Form1::captionTextHeight
  IL_0030:  ldarg.0
  IL_0031:  ldfld      float32 WindowsFormsApplication1.Form1::captionLineWidth
  IL_0036:  ldc.r4     2.
  IL_003b:  div
  IL_003c:  add
  IL_003d:  callvirt   instance void [System.Drawing]System.Drawing.Graphics::DrawLine(class [System.Drawing]System.Drawing.Pen,
                                                                                       float32,
                                                                                       float32,
                                                                                       float32,
                                                                                       float32)
Поправка: вывод неверный, так как JIT дополнительно оптимизирует при выполнении, значение вычисляется один раз (см. ниже)



Message 876

Date: 23.03.2017 14:37:19

А, ну да. Я забыл, что в CLR JIT занимается оптимизацией. Действительно, введение промежуточной переменной не дает выигрыша.

Тем не менее, использование умножения вместо степени, по моим измерениям, дает существенный выигрыш

 class Program
    {
        const int N = 10000000;
        static Random r=new Random();

        static double Magic(double x, double y)
        {
            return 5.1 * r.NextDouble() * x + 6.6 * r.NextDouble() * y;
        }

        static void Main(string[] args)
        {
            Stopwatch s;
            Random rnd;
            int i,k,m;
            double x, y,z,t;

            s = new Stopwatch();
            rnd = new Random();
            Console.WriteLine("Вычисление степени с помощью Math.Pow...");
            s.Start();
            for (i = 0; i < N; i++)
            {
                x = rnd.NextDouble() * 10.0;
                y = Math.Pow(x, 2);
                if (y == 100.0) Console.WriteLine("Bingo!");
            }
            s.Stop();
            Console.WriteLine("t=" + s.ElapsedMilliseconds.ToString());

            s = new Stopwatch();
            rnd = new Random();
            Console.WriteLine("Вычисление степени с помощью умножения...");
            s.Start();
            for (i = 0; i < N; i++)
            {
                x = rnd.NextDouble() * 10.0;
                y = x * x;
                if (y == 100.0) Console.WriteLine("Bingo!");
            }
            s.Stop();
            Console.WriteLine("t=" + s.ElapsedMilliseconds.ToString());
            /* ------------------------------------------------------------------*/

            s = new Stopwatch();
            rnd = new Random();
            Console.WriteLine("Вычисление частного делением...");
            s.Start();
            for (i = 0; i < N; i++)
            {
                k = rnd.Next();
                m = k / 2;
                if (m == 12345) Console.WriteLine("JackPot!");
            }
            s.Stop();
            Console.WriteLine("t=" + s.ElapsedMilliseconds.ToString());

            s = new Stopwatch();
            rnd = new Random();
            Console.WriteLine("Вычисление частного сдвигом...");
            s.Start();
            for (i = 0; i < N; i++)
            {
                k = rnd.Next();
                m = k >> 1;
                if (m == 12345) Console.WriteLine("JackPot!");
            }
            s.Stop();
            Console.WriteLine("t=" + s.ElapsedMilliseconds.ToString());

            /* ------------------------------------------------------------------*/

            s = new Stopwatch();
            rnd = new Random();
            Console.WriteLine("Расчет без промежуточной переменной...");
            s.Start();
            for (i = 0; i < N; i++)
            {
                x = rnd.NextDouble() * 10.0;
                y = rnd.NextDouble() * 5.0;
                z = Magic(x + y, x + y);
                if (z == 1111.11) Console.WriteLine("Magic!");
            }
            s.Stop();
            Console.WriteLine("t=" + s.ElapsedMilliseconds.ToString());

            s = new Stopwatch();
            rnd = new Random();
            Console.WriteLine("Расчет с промежуточной переменной...");
            s.Start();
            for (i = 0; i < N; i++)
            {
                x = rnd.NextDouble() * 10.0;
                y = rnd.NextDouble() * 5.0;
                t=x + y;
                z = Magic(t, t);
                if (z == 1111.11) Console.WriteLine("Magic!");
            }
            s.Stop();
            Console.WriteLine("t=" + s.ElapsedMilliseconds.ToString());

            Console.ReadKey();
        }
    }  


Автор: VadimTagil

Главная страница - Список тем - Репозиторий на GitHub