What is the fastest way to initialize a multidimensional array for values ​​other than the default values ​​in .NET?

How to initialize a multidimensional array of primitive type as quickly as possible?

I am stuck with using multidimensional arrays. My problem is performance. The following procedure initializes a 100x100 array in approx. 500 ticks. Delete initialization results int.MaxValue approx. 180 ticks for a cycle only. Approximately 100 ticks for creating an array without a loop and without initializing int.MaxValue.

  • Such routines are usually called from several hundred thousand to several million times during the "start".
  • The size of the array does not change at run time, and the arrays are created once in a while, are used, then discarded and a new array is created.
  • A run that can last from one minute (using 10x10 arrays) to forty-five minutes (100x100).
  • The application creates arrays int, bool and struct.
  • At the same time, several “starts” can be performed, but not because performance is greatly degraded.
  • I use 100x100 as the baseline.

I am open to suggestions on how to optimize this initialization without array initialization. One of my ideas was to use a smaller primitive type when available. For example, using a byte instead of an int saves 100 ticks. I would be pleased with this, but I hope that I do not need to change the primitive data type.

    public int[,] CreateArray(Size size) {
        int[,] array = new int[size.Width, size.Height];
        for (int x = 0; x < size.Width; x++) {
            for (int y = 0; y < size.Height; y++) {
                array[x, y] = int.MaxValue;
            }
        }
        return array;
    }

Up to 450 ticks with the following:

    public int[,] CreateArray1(Size size) {
        int iX = size.Width;
        int iY = size.Height;
        int[,] array = new int[iX, iY];
        for (int x = 0; x < iX; x++) {
            for (int y = 0; y < iY; y++) {
                array[x, y] = int.MaxValue;
            }
        }
        return array;
    }

CreateArray5; Accepted implementation: Restriction: it is impossible to change the size, it is possible to change

165 2800 . (. .) stackalloc , ​​ private static.

    private static bool _arrayInitialized5;
    private static int[,] _array5;

    public static int[,] CreateArray5(Size size) {
        if (!_arrayInitialized5) {
            int iX = size.Width;
            int iY = size.Height;
            _array5 = new int[iX, iY];
            for (int x = 0; x < iX; x++) {
                for (int y = 0; y < iY; y++) {
                    _array5[x, y] = int.MaxValue;
                }
            }
            _arrayInitialized5 = true;
        }
        return (int[,])_array5.Clone();
    }

CreateArray8; ; :

165 " " . (. .) , , CreateArray9.

    public unsafe static int[,] CreateArray8(Size size) {
        int iX = size.Width;
        int iY = size.Height;
        int[,] array = new int[iX, iY];
        fixed (int* pfixed = array) {
            int count = array.Length;
            for (int* p = pfixed; count-- > 0; p++)
                *p = int.MaxValue;
        }
        return array;
    }

. , .

, (LOH), . , .

Stackalloc

stackalloc , . , . , stackalloc.

CreateArray8; /

CLR unsafe, .

CreateArray5;

, , . , / . . Dan Tao .

300%?

, 300% - , ( 500 165 ).


"". "" , .

:

  • Grid<int>; initalize: 4348, 4336, 4339, 4654
  • Grid<bool>; : 2692, 2684, 3916, 2680
  • Grid<Color>; : 3747, 4630, 2702, 2708

:

  • Grid<int>; : 185, 159, 152, 290
  • Grid<bool>; : 39, 36, 44, 46
  • Grid<Color>; : 2229, 2431, 2460, 2496

    public class Grid<T> {
        private T[,] _array;
        private T _value;
        private bool _initialized;
        private int _x;
        private int _y;
        public Grid(Size size, T value, bool initialize) {
            _x = size.Width;
            _y = size.Height;
            _value = value;
            if (initialize) {
                InitializeArray();
            }
        }
        private void InitializeArray() {
            int iX = _x;
            int iY = _y;
            _array = new T[iX, iY];
            for (int y = 0; y < iY; y++) {
                for (int x = 0; x < iX; x++) {
                    _array[x, y] = _value;
                }
            }
            _initialized = true;
        }
        public T[,] CreateArray() {
            if (!_initialized) {
                InitializeArray();
            }
            return (T[,])_array.Clone();
        }
    }
    
+5
7

Clone: , . , , , Size . , , :

  • , .
  • Dictionary<Size, int[,]> ( , Size - ), , Size. .
  • Clone.

, 3, :

1. Width Height , Size .

static int[,] CreateArray(Size size) {
    int w = size.Width;
    int h = size.Height;

    int[,] array = new int[w, h];
    for (int x = 0; x < w; x++) {
        for (int y = 0; y < h; y++) {
            array[x, y] = int.MaxValue;
        }
    }

    return array;
}

1000x1000, 120000 140000 .

2. , , .

static int[,] CreateArray(Size size) {
    int w = size.Width;
    int h = size.Height;

    int[,] array = new int[w, h];
    Action<int[,], int, int> fillFirstHalf = FillArray;
    Action<int[,], int, int> fillSecondHalf = FillArray;

    var firstResult = fillFirstHalf.BeginInvoke(array, 0, h / 2, null, null);
    var secondResult = fillSecondHalf.BeginInvoke(array, h / 2, h, null, null);

    fillFirstHalf.EndInvoke(firstResult);
    fillSecondHalf.EndInvoke(secondResult);

    return array;
}

static void FillArray(int[,] array, int ystart, int yend) {
    int w = array.GetLength(0);

    for (int x = 0; x < w; ++x) {
        for (int y = ystart; y < yend; ++y) {
            array[x, y] = int.MaxValue;
        }
    }
}

, , , , 100x100, . 1000x1000 , 70 . ( 120- , , ).

, , (.. , 500 ), , . ; .

3. unsafe.

: , .NET *: , "" , . , 10x2 , 20x1; 10x10 , , 100x1 ..

, . , . , .

* , .NET , , "".

fixed unsafe :

static int[,] CreateArray(Size size) {
    int w = size.Width;
    int h = size.Height;

    int[,] array = new int[w, h];
    unsafe {
        fixed (int* ptr = array) {
            for (int i = 0; i < w * h; ++i)
                ptr[i] = int.MaxValue;
        }
    }

    return array;
}

() - CreateArray №2, FillArray :

static void FillArray(int[,] array, int ystart, int yend) {
    int w = array.GetLength(0);

    unsafe {
        fixed (int* p = array) {
            for (int i = w * ystart; i < w * yend; ++i)
                p[i] = int.MaxValue;
        }
    } 
}

, , , , , unsafe .


stackalloc: , . stackalloc:

expr type , ; ptr. ( fixed). , ( )

, , , stackalloc , .

+4

# (), [ ] .

# , . , . .

+3

static unsafe Ticks. .

  • CreateArray; : 521, 464, 453, 474
  • CreateArray; : 430, 423, 418, 454
  • CreateArray; : 485, 464, 435, 414
  • CreateArray; : 476, 450, 433, 405

stackalloc. , , , unsafe. , int.MaxValue, , Clone . .

Clone . Array.Clone . , CreateArray, .

, , stackalloc .

  • CreateArray5; pre-initialize: 2663, 3036
  • CreateArray5; clone: ​​ 157, 172

    private static bool _arrayInitialized5;
    private static int[,] _array5;
    
    public static int[,] CreateArray5(Size size) {
        if (!_arrayInitialized5) {
            int iX = size.Width;
            int iY = size.Height;
            _array5 = new int[iX, iY];
            for (int x = 0; x < iX; x++) {
                for (int y = 0; y < iY; y++) {
                    _array5[x, y] = int.MaxValue;
                }
            }
            _arrayInitialized5 = true;
        }
        return (int[,])_array5.Clone();
    }
    

    int[,] actual;

    int iHi = 10000 * 10 * 2; 
    //'absolute minimum times array will be created   (200,000)
    //'could be as high as 10000 * 10 * 20? * 50? (100,000,000?)

    Stopwatch o;

    //'pre-initialize
    o = Stopwatch.StartNew();
    actual = CreateArray5(new Size(100, 100));
    o.Stop();
    Trace.WriteLine(o.ElapsedTicks, "CreateArray5; pre-initialize");
    o = Stopwatch.StartNew();
    for (int i = 0; i < iHi; i++) { actual = CreateArray5(new Size(100, 100)); }
    o.Stop();
    Trace.WriteLine(o.ElapsedTicks / iHi, "CreateArray5; static unsafe clone");
+2

, . , - .

, for(x) ... for(y) for(y) ... for(x).

+1

, , .

, , For, 64 , 0 63, 64 127 .. Parallel.For..

public int[,] CreateArray(Size size) { 
    int[,] array = new int[size.Width, size.Height]; 
    System.Threading.Paralle.For (0,size.Width, 
      x=>{ 
        for (int y = 0; y < size.Height; y++) { 
            array[x, y] = int.MaxValue; 
        } 
      }
    ); 
    return array; 
} 

.NEt 4, .NET 3.51 codeplex.

0

165. . CreateArray8.

" " CodeProject http://www.codeproject.com/KB/dotnet/arrays.aspx, jdk. (@jdk, .) , . 165. , . (. .)

, , CreateArray9.

  • CreateArray3; : 501, 462, 464, 462
  • CreateArray7; (y, x): 452, 451, 444, 429
  • CreateArray8; single_for: 187, 173, 156, 145

[TestClass]
public class CreateArrayTest {

    public static unsafe int[,] CreateArray3(Size size) {
        int iX = size.Width;
        int iY = size.Height;
        int[,] array = new int[iX, iY];
        for (int x = 0; x < iX; x++) {
            for (int y = 0; y < iY; y++) {
                array[x, y] = int.MaxValue;
            }
        }
        return array;
    }

    public unsafe static int[,] CreateArray7(Size size) {
        int iX = size.Width;
        int iY = size.Height;
        int[,] array = new int[iX, iY];
        for (int y = 0; y < iY; y++) {
            for (int x = 0; x < iX; x++) {
                array[x, y] = int.MaxValue;
            }
        }
        return array;
    }

    public unsafe static int[,] CreateArray8(Size size) {
        int iX = size.Width;
        int iY = size.Height;
        int[,] array = new int[iX, iY];
        fixed (int* pfixed = array) {
            int count = array.Length;
            for (int* p = pfixed; count-- > 0; p++)
                *p = int.MaxValue;
        }
        return array;
    }

    public unsafe static int[,] CreateArray9(Size size) {
        int iX = size.Width;
        int iY = size.Height;
        void* array = stackalloc int[iX * iY];
        int count = iX * iY;
        for (int* p = (int*)array; count-- > 0; p++)
            *p = int.MaxValue;

        //return (int[,])array; //how to return?
        return new int[1, 1];
    }

    [TestMethod()]
    public void CreateArray_Test() {

        int[,] actual;

        int iHi = 10000 * 10 * 2;
        //'absolute minimum times array will be created   (200,000)
        //'could be as high as 10000 * 10 * 20? * 50? (100,000,000?)

        Stopwatch o;

        o = Stopwatch.StartNew();
        for (int i = 0; i < iHi; i++) { actual = CreateArray3(new Size(100, 100)); }
        o.Stop();
        Trace.WriteLine(o.ElapsedTicks / iHi, "CreateArray3; static unsafe");

        o = Stopwatch.StartNew();
        for (int i = 0; i < iHi; i++) { actual = CreateArray7(new Size(100, 100)); }
        o.Stop();
        Trace.WriteLine(o.ElapsedTicks / iHi, "CreateArray7; static unsafe for(y,x)");

        o = Stopwatch.StartNew();
        for (int i = 0; i < iHi; i++) { actual = CreateArray8(new Size(100, 100)); }
        o.Stop();
        Trace.WriteLine(o.ElapsedTicks / iHi, "CreateArray8; static unsafe pointer single_for");

    }

}
0

Class Generic "Clone".

  • MDArray; clone class initalize: 2444, 2587, 2421, 2406
  • MDArray; clone class: 440, 362, 198, 139
  • Grid<int>; : 5344, 5334, 5693, 5272
  • Grid<int>; : 187, 204, 199, 288
  • Grid<bool>; : 3585, 3537, 3552, 3569
  • Grid<bool>; : 37, 44, 36, 43
  • Grid<Color>; : 4139, 3536, 3503, 3533
  • Grid<Color>; : 2737, 3137, 2414, 2171

[TestClass]
public class CreateArrayTest {

    public class MDArray {
        private bool _initialized;
        private int[,] _array;
        private int _x;
        private int _y;
        private int _value;
        public MDArray(Size size, int value, bool initialize) {
            _x = size.Width;
            _y = size.Height;
            _value = value;
            if (initialize) {
                InitializeArray();
            }
        }
        private void InitializeArray() {
            int iX = _x;
            int iY = _y;
            _array = new int[iX, iY];
            for (int y = 0; y < iY; y++) {
                for (int x = 0; x < iX; x++) {
                    _array[x, y] = _value;
                }
            }
            _initialized = true;
        }
        public int[,] CreateArray() {
            if (!_initialized) {
                InitializeArray();
            }
            return (int[,])_array.Clone();
        }
    }

    public class Grid<T> {
        private T[,] _array;
        private T _value;
        private bool _initialized;
        private int _x;
        private int _y;
        public Grid(Size size, T value, bool initialize) {
            _x = size.Width;
            _y = size.Height;
            _value = value;
            if (initialize) {
                InitializeArray();
            }
        }
        private void InitializeArray() {
            int iX = _x;
            int iY = _y;
            _array = new T[iX, iY];
            for (int y = 0; y < iY; y++) {
                for (int x = 0; x < iX; x++) {
                    _array[x, y] = _value;
                }
            }
            _initialized = true;
        }
        public T[,] CreateArray() {
            if (!_initialized) {
                InitializeArray();
            }
            return (T[,])_array.Clone();
        }
    }

    [TestMethod()]
    public void CreateArray_Test() {

        int[,] actual;

        int iHi = 10000 * 10 * 2; //'absolute minimum times array will be created   (200,000)
        //                          'could be as high as 10000 * 10 * 20? * 50? (100,000,000?)

        Stopwatch o;

        o = Stopwatch.StartNew();
        MDArray oMDArray = new MDArray(new Size(100, 100), int.MaxValue, true);
        o.Stop();
        Trace.WriteLine(o.ElapsedTicks, "     MDArray; clone class initalize");
        o = Stopwatch.StartNew();
        for (int i = 0; i < iHi; i++) { actual = oMDArray.CreateArray(); }
        o.Stop();
        Trace.WriteLine(o.ElapsedTicks / iHi, "     MDArray; clone class");

        o = Stopwatch.StartNew();
        Grid<int> oIntMap = new Grid<int>(new Size(100, 100), int.MaxValue, true);
        o.Stop();
        Trace.WriteLine(o.ElapsedTicks, "   Grid<int>; generic clone class initalize");
        o = Stopwatch.StartNew();
        for (int i = 0; i < iHi; i++) { actual = oIntMap.CreateArray(); }
        o.Stop();
        Trace.WriteLine(o.ElapsedTicks / iHi, "   Grid<int>; generic clone class");

        bool[,] fActual;
        o = Stopwatch.StartNew();
        Grid<bool> oBolMap = new Grid<bool>(new Size(100, 100), true, true);
        o.Stop();
        Trace.WriteLine(o.ElapsedTicks, "  Grid<bool>; generic clone class initalize");
        o = Stopwatch.StartNew();
        for (int i = 0; i < iHi; i++) { fActual = oBolMap.CreateArray(); }
        o.Stop();
        Trace.WriteLine(o.ElapsedTicks / iHi, "  Grid<bool>; generic clone class");

        Color[,] oActual;
        o = Stopwatch.StartNew();
        Grid<Color> oColMap = new Grid<Color>(new Size(100, 100), Color.AliceBlue, true);
        o.Stop();
        Trace.WriteLine(o.ElapsedTicks, " Grid<Color>; generic clone class initalize");
        o = Stopwatch.StartNew();
        for (int i = 0; i < iHi; i++) { oActual = oColMap.CreateArray(); }
        o.Stop();
        Trace.WriteLine(o.ElapsedTicks / iHi, " Grid<Color>; generic clone class");
    }
}
0

All Articles