2d array with more than 65535 ^ 2 elements & # 8594; array size exceeded supported range

I have a 64-bit PC with 128 GB of RAM, and I use C # and .NET 4.5. I have the following code:

double[,] m1 = new double[65535, 65535];
long l1 = m1.LongLength;

double[,] m2 = new double[65536, 65536]; // Array dimensions exceeded supported range
long l2 = m2.LongLength;

I know <gcAllowVeryLargeObjects enabled="true" />, and I set it to true.

Why can a multidimensional array contain no more than 4294967295 elements? I saw the following answer https://stackoverflow.com> .

I also checked the documentation for gcAllowVeryLargeObjects , and I saw the following remark.

The maximum number of elements in the UInt32.MaxValue array (4294967295).

I can not understand why this limit exists? Is there a workaround? Is there any plan to remove this restriction in the next version of .net?

, , , , Intel MKL.

[DllImport("custom_mkl", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true, SetLastError = false)]
internal static extern lapack_int LAPACKE_dsyevd(
    int matrix_layout, char jobz, char uplo, lapack_int n, [In, Out] double[,] a, lapack_int lda, [In, Out] double[] w);
+4
2

:

CLR

, CLR .

, "".

, . ( O) - . ​​ , , , , , . CLR , . , .

, , .

, , .

, Evk , PInvoke. , , . - .

, , .

, 8 :

long size = (1L << 33);
IntPtr basePointer = System.Runtime.InteropServices.Marshal.AllocHGlobal((IntPtr)size);

! , 8 .

?

, #

""

. . ( C )

, 2D- , .

pointer

""

"" . .

, : PtrToStructure StructureToPtr. (, ) . .

"" .

, :

  • , 2D- .
  • 2D-

, 2D- 1D-


.

, "" , .

inculde:

  • , 64- .
  • , T .
  • .

, , , Marshal.SizeOf , .

, , :

  • 2D- 2D- ( , , - p = x * size + y
  • PInvoke ( )

, .

using static System.Runtime.InteropServices.Marshal;

public class LongArray<T> : IDisposable where T : struct {
    private IntPtr _head;
    private Int64 _capacity;
    private UInt64 _bytes;
    private Int32 _elementSize;

    public LongArray(long capacity) {
        if(_capacity < 0) throw new ArgumentException("The capacity can not be negative");
        _elementSize = SizeOf(default(T));
        _capacity = capacity;
        _bytes = (ulong)capacity * (ulong)_elementSize;

        _head = AllocHGlobal((IntPtr)_bytes);   
    }

    public T this[long index] {
        get {
            IntPtr p = _getAddress(index);

            T val = (T)System.Runtime.InteropServices.Marshal.PtrToStructure(p, typeof(T));

            return val;
        }
        set {
            IntPtr p = _getAddress(index);

            StructureToPtr<T>(value, p, true);
        }
    }

    protected bool disposed = false;
    public void Dispose() {
        if(!disposed) {
            FreeHGlobal((IntPtr)_head);
            disposed = true;
        }
    }

    protected IntPtr _getAddress(long index) {
        if(disposed) throw new ObjectDisposedException("Can't access the array once it has been disposed!");
        if(index < 0) throw new IndexOutOfRangeException("Negative indices are not allowed");
        if(!(index < _capacity)) throw new IndexOutOfRangeException("Index is out of bounds of this array");
        return (IntPtr)((ulong)_head + (ulong)index * (ulong)(_elementSize));
    }
}
+1

"Marshal" MrPaulch, HugeMatrix<T>:

public class HugeMatrix<T> : IDisposable
    where T : struct
{
    public IntPtr Pointer
    {
        get { return pointer; }
    }

    private IntPtr pointer = IntPtr.Zero;

    public int NRows
    {
        get { return Transposed ? _NColumns : _NRows; }
    }

    private int _NRows = 0;

    public int NColumns
    {
        get { return Transposed ? _NRows : _NColumns; }
    }

    private int _NColumns = 0;

    public bool Transposed
    {
        get { return _Transposed; }
        set { _Transposed = value; }
    }

    private bool _Transposed = false;

    private ulong b_element_size = 0;
    private ulong b_row_size = 0;
    private ulong b_size = 0;
    private bool disposed = false;


    public HugeMatrix()
        : this(0, 0)
    {
    }

    public HugeMatrix(int nrows, int ncols, bool transposed = false)
    {
        if (nrows < 0)
            throw new ArgumentException("The number of rows can not be negative");
        if (ncols < 0)
            throw new ArgumentException("The number of columns can not be negative");
        _NRows = transposed ? ncols : nrows;
        _NColumns = transposed ? nrows : ncols;
        _Transposed = transposed;
        b_element_size = (ulong)(Marshal.SizeOf(typeof(T)));
        b_row_size = (ulong)_NColumns * b_element_size;
        b_size = (ulong)_NRows * b_row_size;
        pointer = Marshal.AllocHGlobal((IntPtr)b_size);
        disposed = false;
    }

    public HugeMatrix(T[,] matrix, bool transposed = false)
        : this(matrix.GetLength(0), matrix.GetLength(1), transposed)
    {
        int nrows = matrix.GetLength(0);
        int ncols = matrix.GetLength(1);
        for (int i1 = 0; i1 < nrows; i1++)
            for (int i2 = 0; i2 < ncols; i2++)
                this[i1, i2] = matrix[i1, i2];
    }

    public void Dispose()
    {
        if (!disposed)
        {
            Marshal.FreeHGlobal(pointer);
            _NRows = 0;
            _NColumns = 0;
            _Transposed = false;
            b_element_size = 0;
            b_row_size = 0;
            b_size = 0;
            pointer = IntPtr.Zero;
            disposed = true;
        }
    }

    public void Transpose()
    {
        _Transposed = !_Transposed;
    }

    public T this[int i_row, int i_col]
    {
        get
        {
            IntPtr p = getAddress(i_row, i_col);
            return (T)Marshal.PtrToStructure(p, typeof(T));
        }
        set
        {
            IntPtr p = getAddress(i_row, i_col);
            Marshal.StructureToPtr(value, p, true);
        }
    }

    private IntPtr getAddress(int i_row, int i_col)
    {
        if (disposed)
            throw new ObjectDisposedException("Can't access the matrix once it has been disposed");
        if (i_row < 0)
            throw new IndexOutOfRangeException("Negative row indices are not allowed");
        if (i_row >= NRows)
            throw new IndexOutOfRangeException("Row index is out of bounds of this matrix");
        if (i_col < 0)
            throw new IndexOutOfRangeException("Negative column indices are not allowed");
        if (i_col >= NColumns)
            throw new IndexOutOfRangeException("Column index is out of bounds of this matrix");
        int i1 = Transposed ? i_col : i_row;
        int i2 = Transposed ? i_row : i_col;
        ulong p_row = (ulong)pointer + b_row_size * (ulong)i1;
        IntPtr p = (IntPtr)(p_row + b_element_size * (ulong)i2);
        return p;
    }
}

Intel MKL , :

[DllImport("custom_mkl", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true, SetLastError = false)]
internal static extern lapack_int LAPACKE_dsyevd(
    int matrix_layout, char jobz, char uplo, lapack_int n, [In, Out] IntPtr a, lapack_int lda, [In, Out] double[] w);

IntPtr a HugeMatrix<T> Pointer HugeMatrix<T>.

0

Source: https://habr.com/ru/post/1690851/


All Articles