2
votes

My C++ project main.cpp, compiled with pgcpp from PGI, calls a function cuda() containing CUDA code in a separate file cuda.cu, compiled with nvcc. Unless I wrap the cuda() function with extern "C" in the function declaration and the common header file, I get linking errors (undefined references).

Without extern "C" (symbol name mismatch => undefined reference):

$ nm main.o | grep -y cuda
U cuda__FPfPiT2iN32
$ nm cuda.o | grep -y cuda
T _Z13cudaPfPiS0_iS0_S0_S0_

With extern "C" (symbol name match => linking works fine):

$ nm main.o | grep -y cuda
U cuda
$ nm cuda.o | grep -y cuda
T cuda

It was my impression that nvcc used the host C++ compiler for host code, and that it would therefore mangle symbol names as in C++? What am I doing wrong then?

EDIT: Could this be due to the fact that nvcc actually uses the GNU compiler gcc for host code, and that this compiler mangles names differently than pgcpp?

EDIT2: My system has pgcpp 14.9, gcc 4.4.7, nvcc/CUDA 6.5

1
nvcc in CUDA 6.5 and prior will use the host gnu compiler. PGI tools have both a PGI "native" toolchain and a PGI gnu-compatible toolchain. You can either switch to the PGI gnu-compatible toolchain (i.e. use pgc++ instead of pgcpp), or you can switch to CUDA 7 which can use the PGI toolchain as your host compiler. You may want to study the PGI documentation.Robert Crovella
Indeed this was my first reflex. The PGI User Guide does not indicate any difference between pgc++ and pgcpp. The symbol names are indeed mangled identically when compiling the pure C++ code with pgc++ instead of pgcpp. Thanks!lodhb
Regarding this statement: "The PGI User Guide does not indicate any difference between pgc++ and pgcpp", try looking at page xv of the PGI user guide.Robert Crovella
You are correct. I was given the 2014 version of the user guide.lodhb

1 Answers

2
votes

nvcc uses (on linux) the host gcc/g++ (gnu) toolchain, by default.

PGI offers two slightly different toolchains for compiling C++ code. One toolchain is invoked using the pgcpp tool. This toolchain is not gnu-compatible, and will not necessarily produce gnu-compatible name-mangling. The other toolchain is invoked using the pgc++ tool, and it is advertised as gnu-compatible, and should produce gnu-compatible name mangling.

Linking problems of this type between objects produced by nvcc and PGI tools should be resolved by using the pgc++ tool.

As an aside, with CUDA 7 it is now possible to use the PGI compiler (pgc++) as the host compiler for nvcc. However this is not the crux of the issue here, although switching to that host compiler would fix the linking issue in a similar fashion.

Differences between pgcpp and pgc++ are referred to in current versions of the PGI users guide (e.g. page xv) and the PGI 2015 release notes:

PGI 2015 Features and Performance

•PGI C++ Compiler

◦PGC++ (pgc++) is now default on Linux and OS X. Features include GNU compatible name mangling and language features supporting g++ versions 4.2-4.8.

...

◦pgc++ is also now supported as an NVCC host compiler on Linux

Note that pgc++ is now (2015) considered "default" and pgcpp is listed as "deprecated."