различное поведение инверсии eigen::matrix при компиляции с помощью gcc и nvcc

Я делаю инверсию матрицы (код приведен ниже), используя Eigen (назовем его inversion.cpp). Inversion.cpp компилируется с помощью g++ и дает правильную инверсию.

Теперь я меняю кодовое имя на Inversion.cu и пытаюсь скомпилировать с помощью nvcc. Компиляция завершается неудачно с длинным списком ошибок.

#include <Eigen/Geometry>
using namespace Eigen;
using namespace std;

typedef Matrix<float, 6, 6> Matrix6f;

int main()
{

Matrix6f M;

M<< 0.932322,  0.125848,  -0.85106, -0.313612,  -1.50979, -0.691102,
0.125848,  0.663803, -0.555993,  0.117918, -0.645694, -0.625737,
-0.85106, -0.555993,   1.26442,   0.39079,   1.89422,  0.959306,
-0.313612,  0.117918,   0.39079,   2.70718,   1.84228,   2.12945,
-1.50979, -0.645694,   1.89422,   1.84228,   3.89408,    2.5017,
-0.691102, -0.625737,  0.959306,   2.12945,    2.5017,   3.39874;

cout << "Inverse= " << M.inverse() << endl;

return 0;
}

Ошибки, которые я получаю, когда пытаюсь скомпилировать код с помощью nvcc:

Scanning dependencies of target matrix_inverse
[100%] Linking CXX executable matrix_inverse
CMakeFiles/matrix_inverse.dir/matrix_inverse_generated_matrix_inverse.cu.o: In function `Eigen::internal::compute_inverse<Eigen::Matrix<float, 6, 6, 0, 6, 6>, Eigen::Matrix<float, 6, 6, 0, 6, 6>, 6>::run(Eigen::Matrix<float, 6, 6, 0, 6, 6> const&, Eigen::Matrix<float, 6, 6, 0, 6, 6>&)':
/usr/include/eigen3/Eigen/src/LU/InverseImpl.h:28: undefined reference to `Eigen::MatrixBase<Eigen::Matrix<float, 6, 6, 0, 6, 6> >::partialPivLu() const'
collect2: error: ld returned 1 exit status
CMakeFiles/matrix_inverse.dir/build.make:79: recipe for target 'matrix_inverse' failed
make[2]: *** [matrix_inverse] Error 1
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/matrix_inverse.dir/all' failed
make[1]: *** [CMakeFiles/matrix_inverse.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2

Мои cmakelists:

cmake_minimum_required(VERSION 2.8 FATAL_ERROR)

project(inversion)
INCLUDE_DIRECTORIES (/usr/include/eigen3)

FIND_PACKAGE(CUDA REQUIRED)
INCLUDE_DIRECTORIES(${CUDA_INCLUDE_DIRS})

set(
    CUDA_NVCC_FLAGS
    ${CUDA_NVCC_FLAGS};
    -O3 -gencode arch=compute_52,code=sm_52;
    )

cuda_add_executable (matrix_inverse matrix_inverse.cu)

Журнал компиляции огромен, и ниже я добавлю только некоторые важные части:

/usr/include/eigen3/Eigen/src/LU/InverseImpl.h(335): warning: calling a __host__ function from a __host__ __device__ function is not allowed
          detected during instantiation of "const Eigen::Inverse<Derived> Eigen::MatrixBase<Derived>::inverse() const [with Derived=Eigen::Matrix<float, 6, 6, 0, 6, 6>]" 
/home/krr/temp_codes/eigen/matrix_inverse/src/matrix_inverse.cu(21): here

/usr/include/eigen3/Eigen/src/Core/Inverse.h(58): warning: calling a __host__ function from a __host__ __device__ function is not allowed
          detected during:
            instantiation of "Eigen::Index Eigen::Inverse<XprType>::cols() const [with XprType=Eigen::PartialPivLU<Eigen::Matrix<float, 6, 6, 0, 6, 6>>]" 
/usr/include/eigen3/Eigen/src/Core/AssignEvaluator.h(733): here
            instantiation of "void Eigen::internal::call_assignment_no_alias(Dst &, const Src &, const Func &) [with Dst=Eigen::Matrix<float, 6, 6, 0, 6, 6>, Src=Eigen::Inverse<Eigen::PartialPivLU<Eigen::Matrix<float, 6, 6, 0, 6, 6>>>, Func=Eigen::internal::assign_op<float>]" 
/usr/include/eigen3/Eigen/src/Core/AssignEvaluator.h(712): here
            instantiation of "void Eigen::internal::call_assignment(Dst &, const Src &, const Func &, Eigen::internal::enable_if<<expression>, void *>::type) [with Dst=Eigen::Matrix<float, 6, 6, 0, 6, 6>, Src=Eigen::Inverse<Eigen::PartialPivLU<Eigen::Matrix<float, 6, 6, 0, 6, 6>>>, Func=Eigen::internal::assign_op<float>]" 
/usr/include/eigen3/Eigen/src/Core/AssignEvaluator.h(693): here
            instantiation of "void Eigen::internal::call_assignment(Dst &, const Src &) [with Dst=Eigen::Matrix<float, 6, 6, 0, 6, 6>, Src=Eigen::Inverse<Eigen::PartialPivLU<Eigen::Matrix<float, 6, 6, 0, 6, 6>>>]" 
/usr/include/eigen3/Eigen/src/Core/PlainObjectBase.h(682): here
            instantiation of "Derived &Eigen::PlainObjectBase<Derived>::_set(const Eigen::DenseBase<OtherDerived> &) [with Derived=Eigen::Matrix<float, 6, 6, 0, 6, 6>, OtherDerived=Eigen::Inverse<Eigen::PartialPivLU<Eigen::Matrix<float, 6, 6, 0, 6, 6>>>]" 
/usr/include/eigen3/Eigen/src/Core/Matrix.h(225): here
            [ 4 instantiation contexts not shown ]
            instantiation of "Derived &Eigen::PlainObjectBase<Derived>::_set_noalias(const Eigen::DenseBase<OtherDerived> &) [with Derived=Eigen::Matrix<float, 6, 6, 0, 6, 6>, OtherDerived=Eigen::Inverse<Eigen::Matrix<float, 6, 6, 0, 6, 6>>]" 
/usr/include/eigen3/Eigen/src/Core/PlainObjectBase.h(783): here
            instantiation of "void Eigen::PlainObjectBase<Derived>::_init1<T,OtherDerived>(const Eigen::DenseBase<OtherDerived> &) [with Derived=Eigen::Matrix<float, 6, 6, 0, 6, 6>, T=Eigen::Inverse<Eigen::Matrix<float, 6, 6, 0, 6, 6>>, OtherDerived=Eigen::Inverse<Eigen::Matrix<float, 6, 6, 0, 6, 6>>]" 
/usr/include/eigen3/Eigen/src/Core/Matrix.h(296): here
            instantiation of "Eigen::Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>::Matrix(const T &) [with _Scalar=float, _Rows=6, _Cols=6, _Options=0, _MaxRows=6, _MaxCols=6, T=Eigen::Inverse<Eigen::Matrix<float, 6, 6, 0, 6, 6>>]" 
/usr/include/eigen3/Eigen/src/Core/DenseBase.h(410): here
            instantiation of "Eigen::DenseBase<Derived>::EvalReturnType Eigen::DenseBase<Derived>::eval() const [with Derived=Eigen::Inverse<Eigen::Matrix<float, 6, 6, 0, 6, 6>>]" 
/usr/include/eigen3/Eigen/src/Core/IO.h(248): here
            instantiation of "std::ostream &Eigen::operator<<(std::ostream &, const Eigen::DenseBase<Derived> &) [with Derived=Eigen::Inverse<Eigen::Matrix<float, 6, 6, 0, 6, 6>>]" 
/home/krr/temp_codes/eigen/matrix_inverse/src/matrix_inverse.cu(21): here

/usr/include/eigen3/Eigen/src/Core/Inverse.h(57): warning: calling a __host__ function from a __host__ __device__ function is not allowed
          detected during:
            instantiation of "Eigen::Index Eigen::Inverse<XprType>::rows() const [with XprType=Eigen::PartialPivLU<Eigen::Matrix<float, 6, 6, 0, 6, 6>>]" 
/usr/include/eigen3/Eigen/src/Core/AssignEvaluator.h(733): here
            instantiation of "void Eigen::internal::call_assignment_no_alias(Dst &, const Src &, const Func &) [with Dst=Eigen::Matrix<float, 6, 6, 0, 6, 6>, Src=Eigen::Inverse<Eigen::PartialPivLU<Eigen::Matrix<float, 6, 6, 0, 6, 6>>>, Func=Eigen::internal::assign_op<float>]" 
/usr/include/eigen3/Eigen/src/Core/AssignEvaluator.h(712): here
            instantiation of "void Eigen::internal::call_assignment(Dst &, const Src &, const Func &, Eigen::internal::enable_if<<expression>, void *>::type) [with Dst=Eigen::Matrix<float, 6, 6, 0, 6, 6>, Src=Eigen::Inverse<Eigen::PartialPivLU<Eigen::Matrix<float, 6, 6, 0, 6, 6>>>, Func=Eigen::internal::assign_op<float>]" 
/usr/include/eigen3/Eigen/src/Core/AssignEvaluator.h(693): here
            instantiation of "void Eigen::internal::call_assignment(Dst &, const Src &) [with Dst=Eigen::Matrix<float, 6, 6, 0, 6, 6>, Src=Eigen::Inverse<Eigen::PartialPivLU<Eigen::Matrix<float, 6, 6, 0, 6, 6>>>]" 
/usr/include/eigen3/Eigen/src/Core/PlainObjectBase.h(682): here
            instantiation of "Derived &Eigen::PlainObjectBase<Derived>::_set(const Eigen::DenseBase<OtherDerived> &) [with Derived=Eigen::Matrix<float, 6, 6, 0, 6, 6>, OtherDerived=Eigen::Inverse<Eigen::PartialPivLU<Eigen::Matrix<float, 6, 6, 0, 6, 6>>>]" 
/usr/include/eigen3/Eigen/src/Core/Matrix.h(225): here
            [ 4 instantiation contexts not shown ]
            instantiation of "Derived &Eigen::PlainObjectBase<Derived>::_set_noalias(const Eigen::DenseBase<OtherDerived> &) [with Derived=Eigen::Matrix<float, 6, 6, 0, 6, 6>, OtherDerived=Eigen::Inverse<Eigen::Matrix<float, 6, 6, 0, 6, 6>>]" 
/usr/include/eigen3/Eigen/src/Core/PlainObjectBase.h(783): here
            instantiation of "void Eigen::PlainObjectBase<Derived>::_init1<T,OtherDerived>(const Eigen::DenseBase<OtherDerived> &) [with Derived=Eigen::Matrix<float, 6, 6, 0, 6, 6>, T=Eigen::Inverse<Eigen::Matrix<float, 6, 6, 0, 6, 6>>, OtherDerived=Eigen::Inverse<Eigen::Matrix<float, 6, 6, 0, 6, 6>>]" 
/usr/include/eigen3/Eigen/src/Core/Matrix.h(296): here
            instantiation of "Eigen::Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>::Matrix(const T &) [with _Scalar=float, _Rows=6, _Cols=6, _Options=0, _MaxRows=6, _MaxCols=6, T=Eigen::Inverse<Eigen::Matrix<float, 6, 6, 0, 6, 6>>]" 
/usr/include/eigen3/Eigen/src/Core/DenseBase.h(410): here
            instantiation of "Eigen::DenseBase<Derived>::EvalReturnType Eigen::DenseBase<Derived>::eval() const [with Derived=Eigen::Inverse<Eigen::Matrix<float, 6, 6, 0, 6, 6>>]" 
/usr/include/eigen3/Eigen/src/Core/IO.h(248): here
            instantiation of "std::ostream &Eigen::operator<<(std::ostream &, const Eigen::DenseBase<Derived> &) [with Derived=Eigen::Inverse<Eigen::Matrix<float, 6, 6, 0, 6, 6>>]" 
/home/krr/temp_codes/eigen/matrix_inverse/src/matrix_inverse.cu(21): here

/usr/include/eigen3/Eigen/src/Core/Solve.h(72): warning: calling a __host__ function from a __host__ __device__ function is not allowed
          detected during:
            instantiation of "Eigen::Index Eigen::Solve<Decomposition, RhsType>::rows() const [with Decomposition=Eigen::PartialPivLU<Eigen::Matrix<float, 6, 6, 0, 6, 6>>, RhsType=Eigen::CwiseNullaryOp<Eigen::internal::scalar_identity_op<float>, Eigen::Matrix<float, 6, 6, 0, 6, 6>>]" 
/usr/include/eigen3/Eigen/src/Core/AssignEvaluator.h(733): here
            instantiation of "void Eigen::internal::call_assignment_no_alias(Dst &, const Src &, const Func &) [with Dst=Eigen::Matrix<float, 6, 6, 0, 6, 6>, Src=Eigen::Solve<Eigen::PartialPivLU<Eigen::Matrix<float, 6, 6, 0, 6, 6>>, Eigen::CwiseNullaryOp<Eigen::internal::scalar_identity_op<float>, Eigen::Matrix<float, 6, 6, 0, 6, 6>>>, Func=Eigen::internal::assign_op<float>]" 
/usr/include/eigen3/Eigen/src/Core/AssignEvaluator.h(712): here
            instantiation of "void Eigen::internal::call_assignment(Dst &, const Src &, const Func &, Eigen::internal::enable_if<<expression>, void *>::type) [with Dst=Eigen::Matrix<float, 6, 6, 0, 6, 6>, Src=Eigen::Solve<Eigen::PartialPivLU<Eigen::Matrix<float, 6, 6, 0, 6, 6>>, Eigen::CwiseNullaryOp<Eigen::internal::scalar_identity_op<float>, Eigen::Matrix<float, 6, 6, 0, 6, 6>>>, Func=Eigen::internal::assign_op<float>]" 
/usr/include/eigen3/Eigen/src/Core/AssignEvaluator.h(693): here
            instantiation of "void Eigen::internal::call_assignment(Dst &, const Src &) [with Dst=Eigen::Matrix<float, 6, 6, 0, 6, 6>, Src=Eigen::Solve<Eigen::PartialPivLU<Eigen::Matrix<float, 6, 6, 0, 6, 6>>, Eigen::CwiseNullaryOp<Eigen::internal::scalar_identity_op<float>, Eigen::Matrix<float, 6, 6, 0, 6, 6>>>]" 
/usr/include/eigen3/Eigen/src/Core/PlainObjectBase.h(682): here
            instantiation of "Derived &Eigen::PlainObjectBase<Derived>::_set(const Eigen::DenseBase<OtherDerived> &) [with Derived=Eigen::Matrix<float, 6, 6, 0, 6, 6>, OtherDerived=Eigen::Solve<Eigen::PartialPivLU<Eigen::Matrix<float, 6, 6, 0, 6, 6>>, Eigen::CwiseNullaryOp<Eigen::internal::scalar_identity_op<float>, Eigen::Matrix<float, 6, 6, 0, 6, 6>>>]" 
/usr/include/eigen3/Eigen/src/Core/Matrix.h(225): here
            [ 10 instantiation contexts not shown ]
            instantiation of "Derived &Eigen::PlainObjectBase<Derived>::_set_noalias(const Eigen::DenseBase<OtherDerived> &) [with Derived=Eigen::Matrix<float, 6, 6, 0, 6, 6>, OtherDerived=Eigen::Inverse<Eigen::Matrix<float, 6, 6, 0, 6, 6>>]" 
/usr/include/eigen3/Eigen/src/Core/PlainObjectBase.h(783): here
            instantiation of "void Eigen::PlainObjectBase<Derived>::_init1<T,OtherDerived>(const Eigen::DenseBase<OtherDerived> &) [with Derived=Eigen::Matrix<float, 6, 6, 0, 6, 6>, T=Eigen::Inverse<Eigen::Matrix<float, 6, 6, 0, 6, 6>>, OtherDerived=Eigen::Inverse<Eigen::Matrix<float, 6, 6, 0, 6, 6>>]" 
/usr/include/eigen3/Eigen/src/Core/Matrix.h(296): here
            instantiation of "Eigen::Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>::Matrix(const T &) [with _Scalar=float, _Rows=6, _Cols=6, _Options=0, _MaxRows=6, _MaxCols=6, T=Eigen::Inverse<Eigen::Matrix<float, 6, 6, 0, 6, 6>>]" 
/usr/include/eigen3/Eigen/src/Core/DenseBase.h(410): here
            instantiation of "Eigen::DenseBase<Derived>::EvalReturnType Eigen::DenseBase<Derived>::eval() const [with Derived=Eigen::Inverse<Eigen::Matrix<float, 6, 6, 0, 6, 6>>]" 
/usr/include/eigen3/Eigen/src/Core/IO.h(248): here
            instantiation of "std::ostream &Eigen::operator<<(std::ostream &, const Eigen::DenseBase<Derived> &) [with Derived=Eigen::Inverse<Eigen::Matrix<float, 6, 6, 0, 6, 6>>]" 
/home/krr/temp_codes/eigen/matrix_inverse/src/matrix_inverse.cu(21): here

person user27665    schedule 22.11.2018    source источник
comment
Какие версии/платформа nvcc/g++/Eigen? В прошлом было известно, что эта комбинация плохо сочетается друг с другом... В качестве дополнительного бонуса, можете ли вы добавить точные флаги командной строки?   -  person Avi Ginsburg    schedule 22.11.2018
comment
добавлен cmakelists.txt   -  person user27665    schedule 22.11.2018
comment
В вопросе вы говорите, что получаете длинный список ошибок, но я вижу только одну ошибку, и это ошибка компоновки, а не ошибка компиляции. Это действительно то, что происходит? Ошибка связывания для этой функции-члена класса? Потому что это полностью задокументированное ограничение Eigen -- eigen.tuxfamily.org /bz/show_bug.cgi?id=1089   -  person talonmies    schedule 22.11.2018
comment
@talonmies За исключением того, что в OP есть #include <Eigen/Geometry>, который начинается с включения Eigen/Core и LU, по крайней мере, в версии, которую я проверял (3.3.4). Так что это задокументированное ограничение не должно иметь значения.   -  person Avi Ginsburg    schedule 22.11.2018
comment
Все эти дополнительные выходные данные, которые вы добавили, содержат только предупреждения компилятора, а не ошибки.   -  person talonmies    schedule 22.11.2018


Ответы (1)


Это просто потому, что инверсия матриц больше 4 еще не поддерживается в CUDA.

Чтобы ответить на комментарий talonmies, поскольку файл OP скомпилирован с помощью nvcc, Eigen автоматически включает поддержку CUDA. В частности, метод MatrixBase::inverse() объявлен как host device, потому что если базовое выражение равно 4x4 или меньше, то во время компиляции он будет переходить к коду, совместимому с CUDA. Для более крупных он переходит к несовместимому с cuda коду... Таким образом, следствием этого является то, что CUDA и нетривиальный код, отличный от CUDA, лучше должны быть хорошо разделены в файлах .cu и .cpp.

person ggael    schedule 22.11.2018
comment
Я закончил анализ. - person ggael; 23.11.2018