Compiling C and CUDA code Problems linking CUDA code and C code

Hello,

I’m stuck attempting to link mixed host and device code with pure C code. I get the job done if I just input all my .c and .cu files into the nvcc tool, but I want to get this done in a makefile to save time.

Generally I am sitting on a file called cudacode.cu that contains a mix of host and device code. This I compile into an object file using nvcc (nvcc --compile cudacode.cu -o cudacode.o).

The rest of the code consists of .c files that are also compiled (not linked) with nvcc. The cudacode.cu file uses global functions etc. in these files.

When my Makefile attempts to link these objects together, I get a lot of errors of the type “unresolved reference”. All of these stem from cudacode.cu towards functions in the .c files.

Any ideas?

Are you declaring the C functions as [font=“Courier New”]extern “C”[/font] in the CUDA code? .cu files get compiled as C++, not C.

Suppose your C code is in ccode,c with the corresponding header file ccode.h.

In the simpler cases it suffices to include the header into cudacode.cu as

extern "C" {

#include "ccode.h"

}

Thanks tera, that did the trick. I had to use this extern “C” symbol around the header file of the C libraries, then it went well.

This seems a bit of a backwards view of the problem, or at least the one I’m trying to solve. There is an existing large program in C, with a lot of pretty much non-parallelizeable stuff surrounding a few time-consuming operations that could be re-written as CUDA. So how do I keep the C, yet call the CUDA? I see another thread suggesting wrapper functions, but I’ve not gotten that approach to work yet. Any other suggestions?

Hi james

I don’t consider it as a backwards way of a solution. I also started out with a pure C program. My algorithm for compiling sources with a mix of C and Cuda code is as follows:

– All C source files that involve Cuda code must be renamed to .cu files
– The rest of the sources can be left as is

In the compilation / linking stages I guess there are many ways you could do this through your makefile. I was playing around with this a lot and found the easiest solution was to use nvcc instead of gcc for both compilation and linking, but I figure it is also possible to compile the .cu files to .c files using "nvcc --cuda " and then proceeding with gcc as normal.

And of course, remember that (as far as I can understand from reading this thread) when nvcc compiles .cu code it interprets that code as C++ code. In a typical makefile you will first compile all sources (if necessary) independently, then link them together into an executable. The problem is that if the .cu files include C functions from another .c file, lets say function.c, those functions will be interpreted as C++ functions, which in turn sets special symbol names for those functions. Later, when compiling function.c, those functions will be compiled with normal symbol names. At the linking stage, since the symbol names from the .cu file do not match those of the compiled function.o file, you will get unresolved references. So you need to use the extern “C”{} syntax around headers including external C code functions (have a look at chapter 32.4: http://www.parashift.com/c++-faq-lite/mixing-c-and-cpp.html).

Are there other things to keep in mind when you integrate Cuda code in a C project?

You can also use gcc for linking, as long as you include the CUDA library path with [font=“Courier New”]-L/usr/local/cuda/lib[/font] (or whatever the path is for you) and the CUDA runtime library with [font=“Courier New”]-lcudart[/font].

I’m now trying to use “nvcc --cuda” to compile my .cu files into .cu.c files, but nvcc generates .cu.cpp files!! o.O Why? The nvcc documentation states explicitly that compiling .cu files with nvcc --cuda will generate .c files.

Perhaps I’m doing something wrong. For a simple example, say I have a program which is in main.c. main wants to call a function “wrapper” which calls a CUDA kernel. Both are defined in kernel.cu, which is complete in itself, and does not call any C functions. So nvcc compiles kernel.cu, and produces a .o file which contains the C++ mangled name of wrapper. Because the name is mangled, main.c does not find the function “wrapper” that it’s trying to call.

What I think I need is something that’s the inverse of the C++ extern “C” statement, to tell nvcc not to generate mangled names. It’s a problem I’ve run across occasionally, not unique to nvcc. While it’s easy to call C functions from C++ (or indeed, from almost any language), I’ve never found a way to call C++ functions from C.

Oh, and the link gives me a “file not found” error.

Thanks,

James