Intel MKL LAPACKE_dsyevd with n > 32766 --> 内存不足,无法在 LAPACKE_dsyevd 中分配工作数组
Intel MKL LAPACKE_dsyevd with n > 32766 --> Not enough memory to allocate work array in LAPACKE_dsyevd
我想使用英特尔 MKL(2019 更新 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,它将失败并显示以下错误消息:
Not enough memory to allocate work array in LAPACKE_dsyevd
我的电脑有 128 GB 的内存,应该足够了。我知道 <gcAllowVeryLargeObjects enabled="true" />
并将其设置为 true。我也很清楚 C# 中多维数组的 65535^2 限制,请参阅 。
顺便说一句,我可以使用 MATLAB 为 n = 40000 或更大的矩阵计算特征值分解。我认为 MATLAB 也在后台使用 Intel MKLin 来计算它。
那么我如何使用英特尔 MKL 在 C# 中计算超大矩阵 (n > 40000) 的特征值分解?
我不认为这是你的问题。下面的定义表明 w = new double[n];
在您的情况下太小了。
* LWORK (input) INTEGER
* The dimension of the array WORK.
* If N <= 1, LWORK must be at least 1.
* If JOBZ = 'N' and N > 1, LWORK must be at least 2*N+1.
* If JOBZ = 'V' and N > 1, LWORK must be at least
* 1 + 6*N + 2*N**2.
您确实应该始终执行工作区查询。我知道,文档将此留给用户,但它非常方便,有助于避免您遇到这种情况。那么您知道如何进行工作区查询吗?如果不快回击我。
这似乎是 LAPACKE_dsyevd. Using LAPACKE_dsyevr 的一个错误,它也适用于更大的矩阵。
我已将以下行添加到 MKL
class:
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
class 的以下行:
[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);
我想使用英特尔 MKL(2019 更新 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,它将失败并显示以下错误消息:
Not enough memory to allocate work array in LAPACKE_dsyevd
我的电脑有 128 GB 的内存,应该足够了。我知道 <gcAllowVeryLargeObjects enabled="true" />
并将其设置为 true。我也很清楚 C# 中多维数组的 65535^2 限制,请参阅
顺便说一句,我可以使用 MATLAB 为 n = 40000 或更大的矩阵计算特征值分解。我认为 MATLAB 也在后台使用 Intel MKLin 来计算它。
那么我如何使用英特尔 MKL 在 C# 中计算超大矩阵 (n > 40000) 的特征值分解?
我不认为这是你的问题。下面的定义表明 w = new double[n];
在您的情况下太小了。
* LWORK (input) INTEGER
* The dimension of the array WORK.
* If N <= 1, LWORK must be at least 1.
* If JOBZ = 'N' and N > 1, LWORK must be at least 2*N+1.
* If JOBZ = 'V' and N > 1, LWORK must be at least
* 1 + 6*N + 2*N**2.
您确实应该始终执行工作区查询。我知道,文档将此留给用户,但它非常方便,有助于避免您遇到这种情况。那么您知道如何进行工作区查询吗?如果不快回击我。
这似乎是 LAPACKE_dsyevd. Using LAPACKE_dsyevr 的一个错误,它也适用于更大的矩阵。
我已将以下行添加到 MKL
class:
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
class 的以下行:
[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);