Hello All,

I am writing an image processing application in C# that needs to be speed optimized for faster performance.

I have been told that using Unsafe Code together with Pointers can speed my algorithm up significantly. Unfortunately, I have no experience with Pointers at all.

How can I make the following example code work with Pointers? (The example multiplies a 640 x 480 pixel images' pixel values by 2, and copies those new values into another 640 x 480 image)

Example:

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        double[,] Redmap = new double[640, 480];
        double[,] Greenmap = new double[640, 480];
        double[,] Bluemap = new double[640, 480];


        double[,] Redmap2 = new double[640, 480];
        double[,] Greenmap2 = new double[640, 480];
        double[,] Bluemap2 = new double[640, 480];



        for (int y = 0; y < 480; y++)
                {

            for (int x = 0; x < 640; x++)
                    {

                Redmap2[x, y] = Redmap[x, y] * 2;

                Greenmap2[x, y] = Greenmap[x, y] * 2;

                Bluemap2[x, y] = Bluemap[x, y] * 2;

                    }
              }



xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Thanks in advance for any help provided!

One thing you can do is parallelize this method. Since no values depend on any other values I'd parallelize at the 'y' index level. You can also use shifting (which is generally faster than multiplication) since you are multiplying by two.

Comments
Yes! Binary, I forgot.

You may want to review this article.
http://www.codeproject.com/Articles/3467/Arrays-UNDOCUMENTED

I also remebered reading somewhere that the outermost dimension should be iterated before the inner ones. If I recall correctly, it has something to do with the layout in memory, but don't quote me on that.

I ran a test case of your original versus flipping the iteration sequence and it made a big improvement. I also tried using jagged arrays as mentioned in the article.

On my test system Vista32, VS2008, the jagged array (modified iterator sequnce) had the best performance. Approx 35% of original time.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();

        public Form1()
        {
            InitializeComponent();

            if (System.Diagnostics.Stopwatch.IsHighResolution)
            {
                Console.WriteLine("Operations timed using the system's high-resolution performance counter.");
            }
            else
            {
                Console.WriteLine("Operations timed using the DateTime class.");
            }

        }

        int iterations = 100;

        private void button1_Click(object sender, EventArgs e)
        { // original
            button1.Enabled = false;
            GC.Collect(); // just for performance testing
            sw.Reset();
            sw.Start();

            double[,] Redmap = new double[640, 480];
            double[,] Greenmap = new double[640, 480];
            double[,] Bluemap = new double[640, 480];


            double[,] Redmap2 = new double[640, 480];
            double[,] Greenmap2 = new double[640, 480];
            double[,] Bluemap2 = new double[640, 480];


            for (int i = 0; i < iterations; i++)
            {
                for (int y = 0; y < 480; y++)
                {

                    for (int x = 0; x < 640; x++)
                    {
                        Redmap2[x, y] = Redmap[x, y] * 2;
                        Greenmap2[x, y] = Greenmap[x, y] * 2;
                        Bluemap2[x, y] = Bluemap[x, y] * 2;
                    }
                }
            }
            sw.Stop();
            Console.WriteLine(sw.ElapsedMilliseconds);
            button1.Enabled = true;

        }


        private void button2_Click(object sender, EventArgs e)
        { //Original, but Modified iterator sequence

            button2.Enabled = false;
            GC.Collect(); // just for performance testing
            sw.Reset();
            sw.Start();

            double[,] Redmap = new double[640, 480];
            double[,] Greenmap = new double[640, 480];
            double[,] Bluemap = new double[640, 480];


            double[,] Redmap2 = new double[640, 480];
            double[,] Greenmap2 = new double[640, 480];
            double[,] Bluemap2 = new double[640, 480];


            for (int i = 0; i < iterations; i++)
            {
                for (int x = 0; x < 640; x++)
                {

                    for (int y = 0; y < 480; y++)
                    {
                        Redmap2[x, y] = Redmap[x, y] * 2;
                        Greenmap2[x, y] = Greenmap[x, y] * 2;
                        Bluemap2[x, y] = Bluemap[x, y] * 2;
                    }
                }
            }
            sw.Stop();
            Console.WriteLine(sw.ElapsedMilliseconds);
            button2.Enabled = true;

        }

        private void button3_Click(object sender, EventArgs e)
        {  // jagged array

            button3.Enabled = false;
            GC.Collect(); // just for performance testing

            sw.Reset();
            sw.Start();

            double[][] Redmap = new double[640][];
            double[][] Greenmap = new double[640][];
            double[][] Bluemap = new double[640][];

            double[][] Redmap2 = new double[640][];
            double[][] Greenmap2 = new double[640][];
            double[][] Bluemap2 = new double[640][];


            for (int i = 0; i < 640; i++)
            {
                Redmap[i] = new double[480];
                Redmap2[i] = new double[480];
                Greenmap[i] = new double[480];
                Greenmap2[i] = new double[480];
                Bluemap[i] = new double[480];
                Bluemap2[i] = new double[480];
            }

            // note: changed iteration sequence
            for (int i = 0; i < iterations; i++)
            {
                for (int x = 0; x < 640; x++)
                {

                    for (int y = 0; y < 480; y++)
                    {
                        Redmap2[x][y] = Redmap[x][y] * 2;
                        Greenmap2[x][y] = Greenmap[x][y] * 2;
                        Bluemap2[x][y] = Bluemap[x][y] * 2;
                    }
                }

            }
            sw.Stop();

            Console.WriteLine(sw.ElapsedMilliseconds);
            button3.Enabled = true;

        }

    }

}

Edited 4 Years Ago by TnTinMN: typo

Yep, jaggad arrays work better do to the way they are layed out in memory. I wrote something a while back about matrix multiplication and using jagged arrays ...

This article has been dead for over six months. Start a new discussion instead.