同时Graphics.RotateTransform经营业绩不佳不佳、经营业绩、Graphics、RotateTransform

2023-09-03 07:10:11 作者:君踏桃花归

在多个线程运行的并发Graphics.RotateTransform操作时,为什么我看不到一个显著的速度增长?

Why don't I see a significant speed increase when running concurrent Graphics.RotateTransform operations across multiple threads?

这个例子演示了边际性能提升:

This example demonstrates the marginal performance increase:

    static Bitmap rotate(Bitmap bitmap, float angle)
    {
        Bitmap rotated = new Bitmap(bitmap.Width, bitmap.Height);
        using (Graphics g = Graphics.FromImage(rotated))
        {
            g.TranslateTransform((float)bitmap.Width / 2, (float)bitmap.Height / 2);
            g.RotateTransform(angle);
            g.TranslateTransform(-(float)bitmap.Width / 2, -(float)bitmap.Height / 2);
            g.DrawImage(bitmap, new Point(0, 0));
        }
        return rotated;
    }

    static void Main(string[] args)
    {
        WebClient client = new WebClient();
        string fileName = Path.GetTempFileName();
        client.DownloadFile("https://m.xsw88.com/allimgs/daicuo/20230903/1520.png", fileName);
        Bitmap original = new Bitmap(fileName);

        DateTime start = DateTime.Now;
        rotateSingleThread(original);
        TimeSpan length = DateTime.Now - start;
        Console.WriteLine(string.Format("Single thread rotate took {0} ms", (int)length.TotalMilliseconds));

        start = DateTime.Now;
        rotateMultiThread(original);
        length = DateTime.Now - start;
        Console.WriteLine(string.Format("Multiple thread rotate took {0} ms", (int)length.TotalMilliseconds));

        Console.WriteLine("Press any key to exit");
        Console.ReadKey();
    }

    static void rotateSingleThread(Bitmap original)
    {
        for (float a = 0; a < 360; a += 0.1F)
        {
            Bitmap rotated = rotate(original, a);
            rotated.Dispose();
        }
    }

    static void rotateMultiThread(Bitmap original)
    {
        int threadCount = Environment.ProcessorCount;
        int groupSize = 360 / threadCount;
        Thread[] threads = new Thread[threadCount];
        Bitmap[] bitmaps = new Bitmap[threadCount];
        for (int x = 0; x < threadCount; x++)
        {
            bitmaps[x] = new Bitmap(original);
            threads[x] = new Thread(delegate(object i)
            {
                int min = (int)i * groupSize; int max = min + groupSize;
                if ((int)i == threadCount - 1) max = 360;
                for (float a = min; a < max + 1; a+= 0.1F)
                {
                    Bitmap rotated = rotate(bitmaps[(int)i], a);
                    rotated.Dispose();
                }
            });
            threads[x].Start(x);
        }
        for (int x = 0; x < threadCount; x++) threads[x].Join();
    }

我能做些什么来提高执行并发Graphics.RotateTransform操作的速度?

What can I do to improve the speed of performing concurrent Graphics.RotateTransform operations?

推荐答案

现在的问题是,那些GDI +调用每个进程(而不是每个线程)的块,所以即使线程并行运行时,调用显卡.... 引起其他线程阻塞。这意味着它结束了处理几乎连续。

The problem is that those GDI+ calls block per process (not per thread), so even though the threads are running in parallel, the calls to graphics.... cause other threads to block. Meaning it ends up processing nearly serially.

请参阅下面的问题,寻求解决方法,最上面的一个建议建立独立的进程不同的答案。看起来你可能最终只创建一个帮助命令行实用程序什么的。你甚至可以得到看中挂钩的标准输入和标准输出,因此您可以通过图像旋转,并取回了新的形象与出IO操作。

See various answers in the question below for workarounds, the top one suggesting creating separate processes. Looks like you might end up just creating a helper command line utility or something. You might even be able to get fancy hook up the stdin and stdout so you could pass the image to rotate and get back the new image with out IO operations.

并行化的GDI +图像大小调整.NET