Конференция "Media" » Аффинное преобразование GDI +
 
  • Рамиль © (03.11.07 15:01) [0]
    Почему System.Drawing.Drawing2D.Matrix такой медленый?

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using System.Drawing.Drawing2D;

    namespace WindowsApplication1
    {
       public partial class Form1 : Form
       {
           private Matrix matrix;
           private float[,] Aphin;
           private int n = 100000;
           public Form1()
           {
               InitializeComponent();
               matrix = new Matrix();
               matrix.Rotate(45);
               matrix.Scale(1.2f, 3.4f);
               Aphin = new float[3, 3];
               float[] a = matrix.Elements;
               Aphin[0, 0] = a[0];
               Aphin[0, 1] = a[1];
               Aphin[1, 0] = a[2];
               Aphin[1, 1] = a[3];
               Aphin[2, 0] = a[4];
               Aphin[2, 1] = a[5];
               Aphin[2, 2] = 1;
           }


           private void MyTransformPoints(PointF[] pts)
           {
               PointF p;
               for (int i = 0; i < pts.Length; i++)
               {
                   p = pts[i];
                   pts[i].X = p.X * Aphin[0, 0] + p.Y * Aphin[1, 0] + Aphin[2, 0];
                   pts[i].Y = p.X * Aphin[0, 1] + p.Y * Aphin[1, 1] + Aphin[2, 1];
               }

           }

           private void button1_Click(object sender, EventArgs e)
           {
               PointF[] Points = new PointF[] {new PointF(12, 34), new PointF(56, 78)}
    ;
               int Ticks = System.Environment.TickCount;
               for (int i = 0; i < n; i++)
                   matrix.TransformPoints(Points);
               Ticks = System.Environment.TickCount - Ticks;
               MessageBox.Show(Ticks.ToString());
           }

           private void button2_Click(object sender, EventArgs e)
           {
               PointF[] Points = new PointF[] { new PointF(12, 34), new PointF(56, 78) }
    ;
               int Ticks = System.Environment.TickCount;
               for (int i = 0; i < n; i++)
                   MyTransformPoints(Points);
               Ticks = System.Environment.TickCount - Ticks;
               MessageBox.Show(Ticks.ToString());

           }
       }
    }


    В первом случае результат ~ 4500
    Во втором ~ 270
    Или я чего то не понимаю?
  • homm © (03.11.07 20:11) [1]
    Забудь про производительность на дотенет. Тем более при использовании GDI+.
  • Рамиль © (03.11.07 20:53) [2]

    > homm ©   (03.11.07 20:11) [1]

    Причем здесь производительность .NET. Вот это ассемблер что ли:
          private void MyTransformPoints(PointF[] pts)
          {
              PointF p;
              for (int i = 0; i < pts.Length; i++)
              {
                  p = pts[i];
                  pts[i].X = p.X * Aphin[0, 0] + p.Y * Aphin[1, 0] + Aphin[2, 0];
                  pts[i].Y = p.X * Aphin[0, 1] + p.Y * Aphin[1, 1] + Aphin[2, 1];
              }

          }


    Работает на порядок быстрее, чем стандартная функция. Мне интересно почему.
    Я сравниваю код для .NET с кодом для .NET. Производительность .NET относительно нативного кода меня в данный момент АБСОЛЮТНО не интересут.
  • Рамиль © (06.11.07 09:09) [3]
    Ну скажите, как можно было реализовать умножение матрицы на вектор, что бы оно так тормозило?
  • homm © (06.11.07 09:38) [4]
    > [3] Рамиль ©   (06.11.07 09:09)
    > Ну скажите, как можно было реализовать умножение матрицы
    > на вектор, что бы оно так тормозило?

    А ты не думаешь, что тормозит не тело функции, а ее вызов? Выкладывали здесь асемблерный код доступа к windows.forms.color.black или что-то в этом роде, там полный северный зверь. Здесь почти то-же самое, System.Drawing.Drawing2D.Matrix.TransformPoints, пока до нее дойдет в дереве сборок…
  • Рамиль © (06.11.07 13:09) [5]

    > homm ©   (06.11.07 09:38) [4]

    Мм..
    Переделал пример(передаю сразу массив на 200 000 точек), matrix.TransformPoints стал выполняться в два раза медленнее чем MyTransofrmPoints в предыдущем примере (получается, что вызов matrix.TransformPoints всего лишь в два раза медленнее чем вызов Form1.MyTransformPoints). А MyTransformPoints вообще за 16.
    Зависмость от количества точек линейная.

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using System.Drawing.Drawing2D;

    namespace WindowsApplication1
    {
       public partial class Form1 : Form
       {
           private Matrix matrix;
           private float[,] Aphin;
           private PointF[] points;
           public Form1()
           {
               InitializeComponent();
               matrix = new Matrix();
               matrix.Rotate(45);
               matrix.Scale(1.2f, 3.4f);
               Aphin = new float[3, 3];
               float[] a = matrix.Elements;
               Aphin[0, 0] = a[0];
               Aphin[0, 1] = a[1];
               Aphin[1, 0] = a[2];
               Aphin[1, 1] = a[3];
               Aphin[2, 0] = a[4];
               Aphin[2, 1] = a[5];
               Aphin[2, 2] = 1;
               Random r = new Random();
               points = new PointF[200000];
               for (int i = 0; i < 200000; i++)
               {
                   points[i].X = r.Next(1000);
                   points[i].Y = r.Next(1000);
               }


           }

           public virtual void MyTransformPoints(PointF[] pts)
           {
               PointF p;
               for (int i = 0; i < pts.Length; i++)
               {
                   p = pts[i];
                   pts[i].X = p.X * Aphin[0, 0] + p.Y * Aphin[1, 0] + Aphin[2, 0];
                   pts[i].Y = p.X * Aphin[0, 1] + p.Y * Aphin[1, 1] + Aphin[2, 1];
               }

           }

           private void button1_Click(object sender, EventArgs e)
           {
               int Ticks = System.Environment.TickCount;
                   matrix.TransformPoints(points);
               Ticks = System.Environment.TickCount - Ticks;
               Color c = Color.Black;
               MessageBox.Show(Ticks.ToString());
           }


           private void button2_Click(object sender, EventArgs e)
           {
               int Ticks = System.Environment.TickCount;
                   MyTransformPoints(points);
               Ticks = System.Environment.TickCount - Ticks;
               MessageBox.Show(Ticks.ToString());

           }

       }
    }



    MyTransformPoints ~ 16
    Matrix.TransformPoints ~ 550
  • homm © (06.11.07 13:19) [6]
    >           Random r = new Random();
    >           points = new PointF[200000];
    >           for (int i = 0; i < 200000; i++)
    >           {
    >               points[i].X = r.Next(1000);
    >               points[i].Y = r.Next(1000);

    Идея объектно-ориентированного программирования, доведенная до маразма.
  • iZEN © (06.11.07 19:13) [7]

    > homm ©   (06.11.07 13:19) [6]
    >
    > >           Random r = new Random();
    > >           points = new PointF[200000];
    > >           for (int i = 0; i < 200000; i++)
    > >           {
    > >               points[i].X = r.Next(1000);
    > >               points[i].Y = r.Next(1000);
    >
    > Идея объектно-ориентированного программирования, доведенная
    > до маразма.


    dotNet, в отличие от Java 6 Mustang, не умеет инлайнить Get/Set-методы. Каждое обращение к свойству ведёт к вызову геттера.
  • homm © (06.11.07 21:20) [8]
    > [7] iZEN ©   (06.11.07 19:13)

    При чем здесь это? Я о том, что для 2-х функций Random и randomize, и одной переменной RandomSeed создан отдельный класс. В этом маразм. Что там вызывается, инлайн или прерывание биоса, мне без разницы.
  • Рамиль © (07.11.07 09:26) [9]
    Хочу проверить прямым вызовом из dll, но что-то я совсем запутался в этих типах.. Что надо передать в GdipTransformMatrixPoints и правильно ли она экспортирована:
            [DllImport("gdiplus.dll", CharSet = CharSet.Auto)]
           public static extern int GdipTransformMatrixPoints(IntPtr matrix, PointF[] pts, int count);


    В CIL передается NativeMatrix
    IL_0017:  ldfld      native int System.Drawing.Drawing2D.Matrix::nativeMatrix

  • Lamer@fools.ua © (07.11.07 13:25) [10]
    >>iZEN ©   (06.11.07 19:13) [7]

    Та фто Фы гафарите...

    public static class Program
    {
       public class Test
       {
           private int m_value;

           public int Value
           {
               //[MethodImpl(MethodImplOptions.NoInlining)]
               get
               {
                   return m_value;
               }

               //[MethodImpl(MethodImplOptions.NoInlining)]
               set
               {
                   m_value = value;
               }

           }
       }

       public static void Main()
       {
           Test t = new Test();
    00000000  push        esi  
    00000001  mov         ecx,963090h
    00000006  call        FFB21FAC
    0000000b  mov         edx,eax
           t.Value = 123;
    0000000d  mov         dword ptr [edx+4],7Bh
           int value = t.Value;
    00000014  mov         esi,dword ptr [edx+4]
           Console.WriteLine(value);
    00000017  cmp         dword ptr ds:[02301084h],0
    0000001e  jne         0000002A
    00000020  mov         ecx,1
    00000025  call        785158EC
    0000002a  mov         ecx,dword ptr ds:[02301084h]
    00000030  mov         edx,esi
    00000032  mov         eax,dword ptr [ecx]
    00000034  call        dword ptr [eax+000000BCh]
    0000003a  pop         esi  
       }

    0000003b  ret

    public static class Program
    {
       public class Test
       {
           private int m_value;

           public int Value
           {
               [MethodImpl(MethodImplOptions.NoInlining)]
               get
               {
                   return m_value;
               }

               [MethodImpl(MethodImplOptions.NoInlining)]
               set
               {
                   m_value = value;
               }

           }
       }

       public static void Main()
       {
           Test t = new Test();
    00000000  push        esi  
    00000001  mov         ecx,963090h
    00000006  call        FFB21FAC
    0000000b  mov         esi,eax
           t.Value = 123;
    0000000d  mov         ecx,esi
    0000000f  mov         edx,7Bh
    00000014  cmp         dword ptr [ecx],ecx
    00000016  call        dword ptr ds:[009630CCh]
           int value = t.Value;
    0000001c  mov         ecx,esi
    0000001e  cmp         dword ptr [ecx],ecx
    00000020  call        dword ptr ds:[009630C8h]
    00000026  mov         esi,eax
           Console.WriteLine(value);
    00000028  cmp         dword ptr ds:[02301084h],0
    0000002f  jne         0000003B
    00000031  mov         ecx,1
    00000036  call        785158EC
    0000003b  mov         ecx,dword ptr ds:[02301084h]
    00000041  mov         edx,esi
    00000043  mov         eax,dword ptr [ecx]
    00000045  call        dword ptr [eax+000000BCh]
    0000004b  pop         esi  
       }

    0000004c  ret

  • iZEN © (08.11.07 16:29) [11]
    00000016  call        dword ptr ds:[009630CCh]
    и
    00000020  call        dword ptr ds:[009630C8h]
    00000026  mov         esi,eax

    Ну точно не инлайнит.
  • Lamer@fools.ua © (12.11.07 12:52) [12]
    >Ну точно не инлайнит.

    И не удивительно. Особенно для тех, кто умеет внимательно читать.
  • Рамиль © (12.11.07 13:05) [13]
    Вы бы лучше по теме что нибудь сказали... Я даже готов согласится, что круче Java ничего нет (но на ней переделывать не буду) :-D
  • homm © (12.11.07 13:38) [14]
    > [13] Рамиль ©   (12.11.07 13:05)
    > Вы бы лучше по теме что нибудь сказали...

    GDI+ отстой?
  • Рамиль © (12.11.07 13:42) [15]
    Ну... такой вывод я и сам могу сделать:) мне б что нить поконструктивнее.
    Хотя бы ответить на
    > Рамиль ©   (07.11.07 09:26) [9]

    на pinvoke.net нет этой функции.
  • antonn © (12.11.07 14:21) [16]
    ну все таки ГДИ+ позволяет, особо не заморачиваясь, выводить линии и текст с антиалиасингом, пускай и относительно медленно :)
  • Algol (12.11.07 14:27) [17]

    > Ну... такой вывод я и сам могу сделать:) мне б что нить
    > поконструктивнее.

    Касаемо сабжа, то кроме как криворукостью индийского программера, действительно, объяснить эффект сложно.
 
Конференция "Media" » Аффинное преобразование GDI +
Есть новые Нет новых   [134431   +10][b:0][p:0.018]