n> 32766的英特尔MKL LAPACKE_dsyevd->内存不足,无法在LAPACKE_dsyevd中分配工作数组

时间:2019-04-03 13:10:57

标签: c# intel-mkl eigenvalue eigenvector lapacke

我想使用Intel MKL(2019 Update 2)中的LAPACKE_dsyevd计算一个实对称矩阵的所有特征值和所有特征向量。

我在C#中具有以下方法:

public static class MKL
{
    public static double[,] SymmetricEig(double[,] a, out double[] w)
    {
        int n1 = a.GetLength(0);
        int n2 = a.GetLength(1);
        if (n1 != n2) throw new System.Exception("Matrix must be square");
        double[,] b = Copy(a);
        int matrix_layout = 101; // row-major arrays
        char jobz = 'V';
        char uplo = 'U';
        int n = n2;
        int lda = n;
        w = new double[n];
        _mkl.LAPACKE_dsyevd(matrix_layout, jobz, uplo, n, b, lda, w);
        return b;
    }
}

使用

class _mkl
{
    [DllImport(DLLName, 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);
}

和以下测试代码:

    int n = 32766; // 32767 or greater --> Not enough memory to allocate work array in LAPACKE_dsyevd
    double[,] A = CreateRandomSymmetricMatrix(n);
    double[] w = new double[n];
    double[,] B = MKL.SymmetricEig(A, out w);

使用

    static double[,] CreateRandomSymmetricMatrix(int n1)
    {
        double[,] m = new double[n1, n1];
        for (int i1 = 0; i1 < n1; i1++)
        {
            for (int i2 = 0; i2 <= i1; i2++)
            {
                m[i1, i2] = r.NextDouble();
                m[i2, i1] = m[i1, i2];
            }
        }
        return m;
    }

如果n大于32766,它将失败并显示以下错误消息:

  

没有足够的内存来分配LAPACKE_dsyevd中的工作数组

我的电脑有128 GB的RAM,应该足够了。我知道<gcAllowVeryLargeObjects enabled="true" />并将其设置为true。我也很清楚C#中多维数组的65535 ^ 2限制,请参见2d-Array with more than 65535^2 elements --> Array dimensions exceeded supported range

通过这种方式,我可以使用MATLAB为n = 40000或更大的矩阵计算特征值分解。而且我认为MATLAB也在后台使用Intel MKL进行计算。

那么我如何使用Intel MKL在C#中计算非常大的矩阵(n> 40000)的特征值分解?

2 个答案:

答案 0 :(得分:0)

我认为这不是您的问题。以下定义表明,new Vue({ el: "#app", template: "<App/>", components: { App } });是您的理想选择。

w = new double[n];

您确实应该始终进行工作区查询。我知道,文档对用户开放,但是它非常方便并且有助于避免出现这种情况。因此,您知道如何进行工作空间查询吗?如果没有击中我,很快就会回来。

答案 1 :(得分:0)

这似乎是LAPACKE_dsyevd的错误。使用LAPACKE_dsyevr可以与较大的矩阵配合使用。

我在MKL类中添加了以下几行:

    public static double[,] SymmetricEigRelativelyRobustRepresentations(double[,] a, out double[] w)
    {
        int n1 = a.GetLength(0);
        int n2 = a.GetLength(1);
        if (n1 != n2) throw new System.Exception("Matrix must be square");
        double[,] b = Copy(a);
        int matrix_layout = 101; // row-major arrays
        char jobz = 'V'; // eigenvalues and eigenvectors are computed
        char range = 'A'; // the routine computes all eigenvalues
        char uplo = 'U'; // a stores the upper triangular part of A 
        int n = n2;
        int lda = n;
        int vl = 0;
        int vu = 0;
        int il = 0;
        int iu = 0;
        double abstol = 0;
        int m = n;
        w = new double[n];
        double[,] z = new double[n, n];
        int ldz = n;
        int[] isuppz = new int[2 * n];
        int info = _mkl.LAPACKE_dsyevr(matrix_layout, jobz, range, uplo, n, b, lda, vl, vu, il, iu, abstol, ref m, w, z, ldz, isuppz);
        return z;
    }

以及_mkl类的以下几行:

    [DllImport(DLLName, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true, SetLastError = false)]
    internal static extern lapack_int LAPACKE_dsyevr(
        int matrix_layout, char jobz, char range, char uplo, lapack_int n, [In, Out] double[,] a, lapack_int lda,
        double vl, double vu, lapack_int il, lapack_int iu, double abstol, [In, Out] ref lapack_int m, [In, Out] double[] w,
        [In, Out] double[,] z, lapack_int ldz, [In, Out] lapack_int[] isuppz);