5
votes

I tried to compile following program (main.cu) with the nvcc (CUDA 5.0 RC):

#include <Eigen/Core>
#include <iostream>

int main( int argc, char** argv )
{
    std::cout << "Pure CUDA" << std::endl;
}

Unfortunately, I get a bunch of warnings and errors I can only explain using nvcc instead of the Microsoft compile.

Is this assumption right? Is there any way to compile Eigen with nvcc? (I actually don´t want to transfer Eigen matrices to the GPU, just access their members)?

If it should not work to compile Eigen with nvcc, is there a nice guide/tutorial about clever ways to seperate host and device code?

I am using CUDA 5.0 RC, Visual Studio 2008, Eigen 3.0.5. To compile the .cu file I used both, the rules file included in CUDA, aswell as the custom build step produced by CMake. Using the CUDA rule file, I targeted the build at compute capability 3.0.

Thanks for your advice.

PS: If I compile the same code with the host compiler it works perfectly.

3
nvcc isn't really meant to be a fully-fledged C++ compiler, so I wouldn't be surprised if it can't compile Eigen. If you only use the Eigen data types in the normal way on the CPU, you can just compile everything that uses CUDA seperately with nvcc and then link this to your actual program, which is otherwise compiled with your C++ compiler of choice. Works at least with GCC, I don't know about Visual Studio but don't know why it shouldn't work (except that it's Microsoft...).leftaroundabout
The part of the code I want to port to CUDA uses Eigen. It´s not that much, but I want a nice solution ... Especially I want to hide the copying of float pointers and that stuff ..GeorgT
If you want to hide that kind of stuff you'll have to wrap your own handles anyway. I really can't see what parts of Eigen you would need in that part of your code; I would make this very simple and only deal with providing an interface between CUDA and proper CPU C++, and then program all the interesting stuff in safe high-level C++. (That worked quite nicely in this project of mine, which is rather a small-scale thing but might be quite similar to what you want.)leftaroundabout
ArrayFire is a fairly close Eigen implementation. See benchmarks of ArrayFire vs Eigen, here: accelereyes.com/products/benchmarks_arrayfire (I know this because I've worked on both Eigen and ArrayFire)arrayfire
Can you provide some of the errors that you are seeing? If Eigen uses C++11, then that is not likely supported by nvcc. However for any less cutting-edge C++, nvcc should handle it fine -- it will pass the C++ host code to the host compiler.harrism

3 Answers

3
votes

NVCC invokes the normal host compiler but not before it has done some preprocessing, so it's likely that NVCC is struggling to parse the Eigen code correctly (especially if it uses C++11 features, but that's unlikely since you say VS2008 works).

I usually advise separating the device code and wrappers into the .cu files and leaving the rest of your application in normal .c/.cpp files to be handled by the host compiler directly. See this answer for some tips on getting this set up with VS2008.

2
votes

It looks like one of the core contributors to Eigen is porting it to be compatible with CUDA. The idea would be to call it from kernel code.

2
votes

Starting with Eigen 3.3, nvcc (7.5) succeeds in passing Eigen code to cl (MSVC 2013) (almost?) correctly. For example, the following code produces only 11 warnings:

#include <Eigen/Core>
#include <iostream>

int main()
{
    std::cout << "Hello Eigen\t";
    std::cout << EIGEN_WORLD_VERSION << "." << EIGEN_MAJOR_VERSION << "." << EIGEN_MINOR_VERSION << "\n";
    std::cout << "Hello nvcc\t";
    std::cout << __CUDACC_VER_MAJOR__ << "." << __CUDACC_VER_MINOR__ << "." << __CUDACC_VER_BUILD__ << "\n";
    return 0;
}

Output as expected (Eigen 3.3rc1):

Hello Eigen 3.2.94
Hello nvcc 7.5.17

But a long list of warnings (see post history if you actually want to see them).

Update:

Unfortunately, using CUDA 8.0 & VS2015 (with both Eigen 3.2.9 & Eigen 3.3rc1) results in compilation errors again:

"operator=" has already been declared in the current scope eigen\src\Core\Block.h 111
"operator=" has already been declared in the current scope eigen\src\Core\Ref.h 89

So close...

Update 2:

This has been fixed in commit 59db051 and is available by either using the development branch or waiting for v3.3 (or 3.3rc2) to actually come out.