BLAS 替换会导致 Linux 中的矩阵乘法失败,但在 Windows 中则不然

BLAS Replacement causes failure of matrix multiplication in Linux but not in windows

本文关键字:失败 但在 Windows 替换 Linux BLAS      更新时间:2023-10-16

我已经下载并安装了软件包qpOASES。

考虑以下代码:

#define ARMA_DONT_USE_CXX11 /* In Cygwin */
#include <armadillo>
int main()
{
    arma::mat A;
    A
        <<0.0119<<0<<arma::endr
        <<0.0237<<0.0119<<arma::endr
        <<0.0354<<0.0437<<arma::endr
        <<0.0469<<0.0354;
    arma::mat B;
    B
    <<1.0<<0<<0<<0<<arma::endr
    <<0<<1.0<<0<<0<<arma::endr
    <<0<<0<<1.0<<0<<arma::endr
    <<0<<0<<0<<1.0;
    std::cout<<"A^T*B:"<<std::endl<<A.t()*B<<std::endl;
    return 0;
}

当我将两个矩阵相乘时,它在窗口中运行正常:

g++ test.cpp -std=c++11 -o bin/example1 -I/cygdrive/d/tmp/qpoases/qpOASES/include -I'C:cygwinusrlocalinclude' -I'C:cygwinusrinclude' -Wall -Wconversion -O3 -lqpOASES -larmadillo -L'C:cygwinusrlocallib' /cygdrive/d/tmp/qpoases/qpOASES/src/BLASReplacement.o -L/cygdrive/d/tmp/qpoases/qpOASES/bin /cygdrive/d/tmp/qpoases/qpOASES/src/LAPACKReplacement.o -Wfatal-errors -Wconversion
./bin/example1
A^T*B:
   0.0119   0.0237   0.0354   0.0469
        0   0.0119   0.0437   0.0354

但它在Linux(Ubuntu)下失败了:

g++ test.cpp -std=c++11 -g -o bin/example1  -Wall -Wconversion -O3 -lqpOASES -larmadillo  -L'qpoases' qpOASES/LAPACKReplacement.o qpOASES/BLASReplacement.o -Wfatal-errors -Wconversion
./bin/example1
A^T*B:
Segmentation fault (core dumped)

我已经意识到导致错误的是BLASReplacement。因此,BLASReplacement程序中删除可以正常工作:

g++ test.cpp -std=c++11 -g -o bin/example1  -Wall -Wconversion -O3 -lqpOASES -larmadillo  -L'qpoases' qpOASES/LAPACKReplacement.o -Wfatal-errors -Wconversion
./bin/example1
A^T*B:
   0.0119   0.0237   0.0354   0.0469
        0   0.0119   0.0437   0.0354

以下是对BLASReplacement.cpp的快速访问。

似乎一起使用qpOASESarmadillo在一起对我来说使用Linux会很麻烦。是什么原因导致此问题,为什么此问题在我的 Windows 中不存在?


更新

我使用代码块作为调试器,发现最后一行导致错误:

typedef double T;
arma_fortran(arma_dgemm)(transA, transB, m, n, k, (const T*)alpha, (const T*)A, ldA, (const T*)B, ldB, (const T*)beta, (T*)C, ldC);

这个包装器的定义是def_blas.hpp

extern "C"
  {
     ...
     void arma_fortran(arma_dgemm)(const char* transA, const char* transB, const blas_int* m, const blas_int* n, const blas_int* k, const double* alpha, const double* A, const blas_int* ldA, const double* B, const blas_int* ldB, const double* beta, double* C, const blas_int* ldC);
     ...
  }

一个指向Armadillo库的 github 分支在这里。

blas_wrapper.hpp内部似乎dgemm armadillo armadilloBLASReplacement.o qpOASES正在发生冲突。绕过它的最佳方法是什么?

我知道

这个老了,但是 qpOASES 在 2021 年解决了这个问题: https://github.com/coin-or/qpOASES/pull/108

回到问题首次发布时,最好的选择可能是在BLASReplacement.hpp/cpp中为所有导出的函数添加前缀,以使其与BLAS API不兼容。