Need help with adding CUDA to MakeFile

Hello,

So I have an existing project that I want to inject CUDA into, but I don’t know how to format the make file for it. The templates I’ve seen for CUDA are different from what I have with my project. So can tweak mine to support CUDA or do I have to totally reformat the make file and in either case, how should it look?

My make file (with a few things cut out for easy reading)

CC=g++

# The _POSIX_* symbols only come into play on systems that are POSIX

# but not SUS.

# SUS3=-D_POSIX_SOURCE -D_POSIX_C_SOURCE=200112L -D_XOPEN_SOURCE=600

HARDEN=-D_FORTIFY_SOURCE

TESTING=-D_FLAT_WORLD

CFLAGS= -pg -g `sdl-config --cflags --libs`

LDFLAGS=-lGL -lGLU -lglut -lpthread  -lSDL_mixer -lGLEW

ALL=mech

mech:	$(ALL)

# -------------------------------------------------------

run.o:	../run.cc ../Common.h

	$(CC) $(CFLAGS) -c $<

MyCoor3.o:	../MyCoor3.cc ../MyCoor3.h

	$(CC) $(CFLAGS) -c $<

... more of the same stuff

GuiTextView.o:	../obj/Gui/GuiTextView.cc ../obj/Gui/GuiTextView.h

	$(CC) $(CFLAGS) -c $<

DevCall.o:	../dev/DevCall.cc ../dev/DevCall.h

	$(CC) $(CFLAGS) -c $<

mech:	run.o MyCoor3.o MyMatr4.o HelperFunc.o ...and so on

	$(CC) -pg $(LDFLAGS) -o $@ $^

clean:

	rm -rf core* *.o *.gch $(ALL)

Lastly when it comes to systems without CUDA, how do I compile it so that any machine can still run it and what do I put in my code so it skips cuda calls if the system doesn’t have CUDA?

Thanks

I find that a few simple changes did the trick for me.

  1. Set up different compiler flags variables, e.g

CFLAGS = -g -O0
NVFLAGS = -g -G -O0

  1. Add a new rule, e.g.

.SUFFIXES: .cpp .c .h .y .l .o .cu

.cu.o:
nvcc (NVFLAGS) -c <

  1. And link everything with nvcc:

(NAME): (OBJS)
nvcc (NVFLAGS) -o @ (OBJS) (LFLAGS) $(LIBS)

Thanks!

I just have a few more questions:

  1. What does the line “.SUFFIXES: .cpp .c .h .y .l .o .cu” do to those file types?

  2. Since it uses Nvidia to link everything, does that mean I can’t use gprof? If not, is there any difference to the flags?

  3. Lastly, if I want to make the program in such a way that when a system doesn’t have CUDA, it still can run. Is there anything I need to do to the MakeFile to have that support, or is that purely done in code?

I haven’t tried you’re suggestions yet, but I’ll let you know if it works or not.

Thanks again!

  1. .SUFFIXES tells make that those are the file types that may be the start of rules. So when you add .cu to the list, and then a .cu.o rule, make works backwards (I think - I’ve never tried to understand the internals of make), seeing that you want say a kernel.o file, that can be created by following the .cu.o rule, and .cu is an ok type for a source file to be. (To be completely honest, it’s probably something that I copied through several iterations from something that worked, without really understanding the details.)

  2. I don’t know. I haven’t used gprof in a long time, since when I did try to use it, it would increase run time by (IIRC) at least an order of magnitude, which is not something you really want when your optimized code might run for hours or days :-).

  3. I’m not sure about that, either. I have different executables (and entirely different development paths) for CUDA & non-CUDA code.

Hi,

I’ll add what I know.

The GNU profiler can be safely used with CUDA compiled programs by invoking the --profile flag with nvcc during compilation. If you invoke nvcc on host code, some compiler specific flags are carried on to the host compiler (including -pg / --profile). Refer to the NVCC manual, chapter “Options altering compiler/linker behavior”. I have used the GNU profiler myself quite a lot, but never got the same analysis as you get with NVIDIA’s (Linux) profile tool, computeprof.

About your final question, no there is no way to have CUDA code execute on hardware which do not have a CUDA enabled GPU that I know of. In previous versions of the CUDA toolkit there has been support for device emulation, but last time I checked that functionality was deprecated. I guess you could implement your program in normal C (without a CUDA enabled coprocessor) and one for CUDA enabled devices, and then steer program compilation with preprocessing symbols (nvcc defines some symbols like NVCC I think).

Thanks for all the help, it works. Anyway, for anyone needing a quick cuda makefile template, here ya go:

CC=g++

HARDEN=-D_FORTIFY_SOURCE

TESTING=-D_FLAT_WORLD

CFLAGS = -g -O0 `sdl-config --cflags --libs`

LDFLAGS= -lGL -lGLU -lglut -lpthread  -lSDL_mixer -lGLEW -lcuda

NVFLAGS = -g -G -O0

.SUFFIXES: .cpp .c .h .y .l .o .cu

ALL=name_of_exe

name_of_exe:	$(ALL)

hostCode.o:	hostCode.cc hostCode.h

	$(CC) $(CFLAGS) -c $<

deviceCode.o:	deviceCode.cu deviceCode.h

	nvcc $(NVFLAGS) -c $<

name_of_exe:	 hostCode.o deviceCode.o

	nvcc $(NVFLAGS) $(LDFLAGS) -o $@ $^

clean:

	rm -rf core* *.o *.gch $(ALL)

Thanks for all the help, it works. Anyway, for anyone needing a quick cuda makefile template, here ya go:

CC=g++

HARDEN=-D_FORTIFY_SOURCE

TESTING=-D_FLAT_WORLD

CFLAGS = -g -O0 `sdl-config --cflags --libs`

LDFLAGS= -lGL -lGLU -lglut -lpthread  -lSDL_mixer -lGLEW -lcuda

NVFLAGS = -g -G -O0

.SUFFIXES: .cpp .c .h .y .l .o .cu

ALL=name_of_exe

name_of_exe:	$(ALL)

hostCode.o:	hostCode.cc hostCode.h

	$(CC) $(CFLAGS) -c $<

deviceCode.o:	deviceCode.cu deviceCode.h

	nvcc $(NVFLAGS) -c $<

name_of_exe:	 hostCode.o deviceCode.o

	nvcc $(NVFLAGS) $(LDFLAGS) -o $@ $^

clean:

	rm -rf core* *.o *.gch $(ALL)

I’m not a Makefile expert by any means, but I don’t believe that the .SUFFIXES rule does anything in the context of your Makefile, since you’re explicitly compiling every source file. That works ok when you have only a couple of sources, but gets tedious when you have a couple of dozen. Also, your “ALL=name_of_exe, name_of_exe: $(ALL)” looks circular. Make might understand it, but I certainly don’t :-)

Also, as you’ve chosen to name your C++ files with a .cc extension instead of .cpp, I think you’d need to change .SUFFIXES to correspond. Then you could add a .cc.o rule, and shorten a more-files Makefile considerably.

I’m not a Makefile expert by any means, but I don’t believe that the .SUFFIXES rule does anything in the context of your Makefile, since you’re explicitly compiling every source file. That works ok when you have only a couple of sources, but gets tedious when you have a couple of dozen. Also, your “ALL=name_of_exe, name_of_exe: $(ALL)” looks circular. Make might understand it, but I certainly don’t :-)

Also, as you’ve chosen to name your C++ files with a .cc extension instead of .cpp, I think you’d need to change .SUFFIXES to correspond. Then you could add a .cc.o rule, and shorten a more-files Makefile considerably.