Multiplying 0x0 * 0xN crashes with EIGEN_USE_BLAS
Summary
Multiplying a 0x0 matrix by a 0-size vector works as expected with Eigen's internal implementation, but when using BLAS it fails with
BLAS error: Parameter number 7 passed to cblas_sgemv had an invalid value
on OSX with -framework Accelerate, or
** On entry to SGEMV parameter number 6 had an illegal value
on Linux with -lblas.
Although obviously an edge case, this behavior is triggered by the LBFGS solver in cppoptlib, which starts off with with a 0xN matrix for the direction set and does some operations on it that become non-trivial as the optimization progresses.
The error is documented behavior in BLAS. Parameter 6 is LDA, and:
LDA - INTEGER.
On entry, LDA specifies the first dimension of A as
declared in the calling (sub) program. LDA must be at
least max( 1, m ). Unchanged on exit.
Eigen passes rhs.outerStride() as LDA, which is 0 for a 0x0 matrix. And even though m is zero, BLAS is unhappy.
It could be fixed by either passing max(1, rhs.outerStride()), or by not calling SGEMV at all if one of the dimensions is zero.
Environment
- Operating System : OSX and Linux
- Architecture : x64 and Arm64
- Eigen Version : 3.4.0
- Compiler Version : clang 14.0.0
- Compile Flags : -O2
- Vector Extension : NEON on OSX-arm64. None on x64
Minimal Example
#define EIGEN_USE_BLAS
#include "Eigen/Dense"
#include <iostream>
int main(int argc, char* argv[])
{
Eigen::MatrixXf m(0,0);
Eigen::VectorXf v(0);
std::cout << "m size = " << m.rows() << "x" << m.cols() << "\n";
std::cout << "v size = " << v.rows() << "x" << v.cols() << "\n";
// Crashes below with EIGEN_USE_BLAS
Eigen::VectorXf p = (m * v);
std::cout << "p size = " << p.rows() << "x" << p.cols() << "\n";
return 0;
}
Steps to reproduce
With the above file as test/eigen_zerosize.cc, it crashes thusly (on OSX):
$ c++ -std=c++20 -O2 -o test/eigen_zerosize test/eigen_zerosize.cc -I /usr/include/eigen3 -framework Accelerate && test/eigen_zerosize
m size = 0x0
v size = 0x1
BLAS error: Parameter number 7 passed to cblas_sgemv had an invalid valuep size = 0x1
On Linux, it prints the error but keeps going:
$ c++ -std=c++20 -O2 -o test/eigen_zerosize test/eigen_zerosize.cc -I /usr/include/eigen3 -lblas && test/eigen_zerosize
m size = 0x0
v size = 0x1
** On entry to SGEMV parameter number 6 had an illegal value
p size = 0x1
What is the current bug behavior?
Crashes in SGEMV
What is the expected correct behavior?
Should produce a 0-size vector, like Eigen's internal operations
Relevant logs
Anything else that might help
-
Have a plan to fix this issue.