从Eigen调用Lapack函数时出现分段错误 我的程序是用C++编写的,我用EGIN库来做矩阵运算。里面有一个巨大的矩阵积,尺寸是50000*1000和1000*50000。所以我尝试从MKL库调用BLAS函数来提高性能。然后在调用dgemm函数时出现分段错误

从Eigen调用Lapack函数时出现分段错误 我的程序是用C++编写的,我用EGIN库来做矩阵运算。里面有一个巨大的矩阵积,尺寸是50000*1000和1000*50000。所以我尝试从MKL库调用BLAS函数来提高性能。然后在调用dgemm函数时出现分段错误,c++,segmentation-fault,eigen,lapack,blas,C++,Segmentation Fault,Eigen,Lapack,Blas,这是密码 double alpha = 1, beta = 0; double *s1; MKL_INT mm1 = q, nn1 = q, kk1 = ncol1; s1 = (double *)malloc(q*q*sizeof(double)); cout << 14 << endl; cblas_dgemm(CblasColMajor, CblasNoTrans, CblasNoTrans,mm1, nn1

这是密码

        double alpha = 1, beta = 0;
    double *s1;
    MKL_INT mm1 = q, nn1 = q, kk1 = ncol1;
    s1 = (double *)malloc(q*q*sizeof(double));
    cout << 14 << endl;

    cblas_dgemm(CblasColMajor, CblasNoTrans, CblasNoTrans,mm1, nn1, kk1, alpha, V.data(), mm1, A01.data(), kk1, beta, s1, mm1);

i、 e:我试过LP64接口和ILP64接口,但都不起作用,有人能帮我吗?我在Linux服务器上运行该程序,内存充足


多谢各位

以下讨论假设:

  • sizeof(双精度)==8
  • MKL_INT
    INT
    ,并且
    sizeof(INT)==4
  • sizeof(std::size\u t)==8
  • CHAR\u位==8
在典型的64位系统中应该是这样

这一行发生了一些非常有趣的事情:

s1 = (double *)malloc(q*q*sizeof(double));
如果
q
50000
,则
q*q
2500000000
。如果
q
int
,则会导致有符号整数溢出,从而导致未定义的行为。在这种特殊情况下,编译器可能只是简单地换行(有效地减去232),结果是
-1794967296

然而,当您将
-1794967296
sizeof(double)
相乘时,这是一种无符号整数类型
std::size\u t
,有趣的事情发生了。如果
size\u t
是64位的,那么编译器需要将
-1794967296
转换为一个无符号的64位数字,从概念上讲,这种转换是通过将264添加到该数字中来实现的,即
18446744071914584320
。当您将其乘以
sizeof(double)
时,它会再次溢出,但无符号溢出定义良好,并返回64位操作数的模264结果,因此最终结果为
18446744059349813248
。(有关计算,请参见此处)

因此,您的原始代码最终尝试分配
18446744059349813248
字节的内存(这几乎是16 EB)。哎哟显然,分配将失败并返回空指针。因为没有检查返回值,所以稍后会出现分段错误

当你把它改写成

s1 = (double *)malloc(sizeof(double) * q * q);

然后首先计算
sizeof(double)*q
。此乘法将
q
转换为
std::size\u t
,但由于
q
为正,因此转换不会影响其值。因此,结果定义良好,是一个
std::size\t
,值为
400000
。第二次乘法同样是定义良好的-
q
再次转换为
std::size\u t
,结果乘法产生
200000000000
,不会溢出
std::size\u t
,因此您的
malloc
调用实际上请求20GB内存。

50000*50000*sizeof(double)
约为20GB(假设8字节
双字节
s)。你检查过你的代码返回值吗?MALLC/<代码>?这个问题被标记为C++,为什么你使用<代码> MalOC 而不是<代码> STD::向量< /代码>?此外,如果您使用的是
malloc
,那么对
free
的调用在哪里?另外:为什么要使用C风格的强制转换?@T.C.,感谢您的提醒,我将内存分配部分更改为“double s1=(double)mkl_malloc(sizeof(double)*nn1*nn1,64)”,并使用ilp接口编译,现在代码可以工作了。您介意回答这个问题吗?我马上接受。@RobertAllanHenniganLeahy,谢谢您的评论,这里我使用CBLAS作为接口来调用BLAS函数,该函数是用fortran编写的。CBLAS是一个C接口,所以我使用malloc(),函数末尾有free()。我使用bpeek查看服务器的实时输出,有时输出很长,我需要使用什么命令将输出重定向到服务器上的文件,以便检查?非常感谢。
s1 = (double *)malloc(q*q*sizeof(double));
s1 = (double *)malloc(sizeof(double) * q * q);