NVCC with C++ application

I’m a newbie to CUDA and parallel programming so forgive me for my mistakes. I have a C++ program with some code in a function that I’d like to run on the GPU. Originally the program is being compiled with gcc/g++ and I’m trying to modify the makefile for the program so I can compile using nvcc but I’m really stuck on how to integrate everything together, especially the linking stage.

This is the original make file

CC = gcc
CCPP = g++

#preprocessor defines
DEFINES = -DUSE_ZLIB

OPTFLAGS = -O3

#CFLAGS = -ansi -pedantic -Wall -Werror -fPIC 
#CFLAGS = -ansi -pedantic -Wall -fPIC 
CFLAGS = -ansi $(OPTFLAGS)

CPPFLAGS = $(OPTFLAGS) -I./include $(DEFINES)
LINKFLAGS = -lz

all : simple

objs =  src/tourtre.o     \
	src/ctArc.o       \
	src/ctBranch.o    \
	src/ctComponent.o \
	src/ctNode.o      \
	src/ctQueue.o     \
	src/ctNodeMap.o	  \
	examples/simple/obj/Data.o \
	examples/simple/obj/Mesh.o \
	examples/simple/obj/main.o 

simple : $(objs)
	$(CCPP)  $(CPPFLAGS) -o simple $^ $(LINKFLAGS)

src/tourtre.o : src/tourtre.c include/tourtre.h src/ctMisc.h include/ctArc.h include/ctNode.h src/ctComponent.h include/ctNode.h src/ctQueue.h src/ctAlloc.h
	$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@

src/ctArc.o : src/ctArc.c include/tourtre.h src/ctMisc.h include/ctArc.h 
	$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@

src/ctBranch.o : src/ctBranch.c include/tourtre.h src/ctMisc.h include/ctBranch.h 
	$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@

src/ctComponent.o : src/ctComponent.c include/tourtre.h src/ctMisc.h src/ctComponent.h 
	$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@

src/ctNode.o : src/ctNode.c include/tourtre.h src/ctMisc.h include/ctNode.h 
	$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@

src/ctQueue.o : src/ctQueue.c include/tourtre.h src/ctMisc.h src/ctQueue.h 
	$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@

src/ctNodeMap.o : src/ctNodeMap.c src/ctNodeMap.h include/ctNode.h src/ctQueue.h src/sglib.h
	$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@

examples/simple/obj/Data.o: examples/simple/src/Data.cpp examples/simple/src/Data.h examples/simple/src/Global.h 
	$(CCPP) $(CPPFLAGS) $(CFLAGS) -c $< -o $@

examples/simple/obj/Mesh.o: examples/simple/src/Mesh.cpp examples/simple/src/Data.h examples/simple/src/Global.h examples/simple/src/Mesh.h 
	$(CCPP) $(CPPFLAGS) $(CFLAGS) -c $< -o $@

examples/simple/obj/main.o: examples/simple/src/main.cpp examples/simple/src/Data.h examples/simple/src/Global.h examples/simple/src/Mesh.h 
	$(CCPP) $(CPPFLAGS) $(CFLAGS) -c $< -o $@




clean :
	-rm -rf src/*.o examples/simple/obj/*.o doc/html

The file that contains the GPU code is in examples/simple/src/Mesh.cpp; I wrote a simple function that isn’t called anywhere yet because I want to get the compilation working. I’ve tried modifying the makefile so that nvcc is used instead of g++:

CC = gcc
CCPP = g++
NVCC = /vol/cuda/8.0.61/bin/nvcc

#preprocessor defines
DEFINES = -DUSE_ZLIB

OPTFLAGS = -O3

#CFLAGS = -ansi -pedantic -Wall -Werror -fPIC 
#CFLAGS = -ansi -pedantic -Wall -fPIC 
CFLAGS = -ansi $(OPTFLAGS)
NVFLAGS = -x cu -Wno-deprecated-gpu-targets

CPPFLAGS = $(OPTFLAGS) -I./include $(DEFINES)
LINKFLAGS = -lz

all : simple

objs =  src/tourtre.o     \
	src/ctArc.o       \
	src/ctBranch.o    \
	src/ctComponent.o \
	src/ctNode.o      \
	src/ctQueue.o     \
	src/ctNodeMap.o	  \
	examples/simple/obj/Data.o \
	examples/simple/obj/Mesh.o \
	examples/simple/obj/main.o 

simple : $(objs)
	$(CCPP)  $(CPPFLAGS) –lcudart -o simple $^ $(LINKFLAGS)

src/tourtre.o : src/tourtre.c include/tourtre.h src/ctMisc.h include/ctArc.h include/ctNode.h src/ctComponent.h include/ctNode.h src/ctQueue.h src/ctAlloc.h
	$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@

src/ctArc.o : src/ctArc.c include/tourtre.h src/ctMisc.h include/ctArc.h 
	$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@

src/ctBranch.o : src/ctBranch.c include/tourtre.h src/ctMisc.h include/ctBranch.h 
	$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@

src/ctComponent.o : src/ctComponent.c include/tourtre.h src/ctMisc.h src/ctComponent.h 
	$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@

src/ctNode.o : src/ctNode.c include/tourtre.h src/ctMisc.h include/ctNode.h 
	$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@

src/ctQueue.o : src/ctQueue.c include/tourtre.h src/ctMisc.h src/ctQueue.h 
	$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@

src/ctNodeMap.o : src/ctNodeMap.c src/ctNodeMap.h include/ctNode.h src/ctQueue.h src/sglib.h
	$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@

examples/simple/obj/Data.o: examples/simple/src/Data.cpp examples/simple/src/Data.h examples/simple/src/Global.h 
	$(CCPP) $(CPPFLAGS) $(CFLAGS) -c $< -o $@

examples/simple/obj/Mesh.o: examples/simple/src/Mesh.cpp examples/simple/src/Data.h examples/simple/src/Global.h examples/simple/src/Mesh.h 
	$(NVCC) $(NVFLAGS) –dlink -c $< -o $@

examples/simple/obj/main.o: examples/simple/src/main.cpp examples/simple/src/Data.h examples/simple/src/Global.h examples/simple/src/Mesh.h 
	$(CCPP) $(CPPFLAGS) $(CFLAGS) -c $< -o $@




clean :
	-rm -rf src/*.o examples/simple/obj/*.o doc/html

I’ve been reading some articles about Separate Compilation and Linking of CUDA C++ Device code (https://devblogs.nvidia.com/parallelforall/separate-compilation-linking-cuda-device-code/) but I can’t seem to get it to work. Honestly I am quite unsure about what I am doing. I’m not sure if it even makes sense to have –dlink -c together because to my knowledge, -c specifies not to link but -dlink specifies to link?

Anyway, when I run make, I get the following error:

make -f Makefile
gcc -O3 -I./include -DUSE_ZLIB -ansi -O3 -c src/tourtre.c -o src/tourtre.o
gcc -O3 -I./include -DUSE_ZLIB -ansi -O3 -c src/ctArc.c -o src/ctArc.o
gcc -O3 -I./include -DUSE_ZLIB -ansi -O3 -c src/ctBranch.c -o src/ctBranch.o
gcc -O3 -I./include -DUSE_ZLIB -ansi -O3 -c src/ctComponent.c -o src/ctComponent.o
gcc -O3 -I./include -DUSE_ZLIB -ansi -O3 -c src/ctNode.c -o src/ctNode.o
gcc -O3 -I./include -DUSE_ZLIB -ansi -O3 -c src/ctQueue.c -o src/ctQueue.o
gcc -O3 -I./include -DUSE_ZLIB -ansi -O3 -c src/ctNodeMap.c -o src/ctNodeMap.o
g++ -O3 -I./include -DUSE_ZLIB -ansi -O3 -c examples/simple/src/Data.cpp -o examples/simple/obj/Data.o
/vol/cuda/8.0.61/bin/nvcc -x cu -Wno-deprecated-gpu-targets –dlink -c examples/simple/src/Mesh.cpp -o examples/simple/obj/Mesh.o
nvcc fatal   : A single input file is required for a non-link phase when an outputfile is specified
Makefile:59: recipe for target 'examples/simple/obj/Mesh.o' failed
make: *** [examples/simple/obj/Mesh.o] Error 1

Help much appreciated.
Thank you

correct, -c and -dlink don’t make sense together.

This target in your makefile:

examples/simple/obj/Mesh.o: examples/simple/src/Mesh.cpp examples/simple/src/Data.h examples/simple/src/Global.h examples/simple/src/Mesh.h 
	$(NVCC) $(NVFLAGS) –dlink -c $< -o $@

is clearly specifying a source->object compile step, so -dlink does not belong there. It also appears to be the only object target that specifies nvcc for compilation, so it does not appear that you should need CUDA separable compilation and linking.

If you want to learn how to build a makefile for cuda separable compilation and linking, you might want to study any of the sample projects that do this, and their associated makefiles.