starting cuda function from a .cc file

Hi,

sorry to disturb you, but I need your help. I have a .cc file and I want to use a cuda function in this file.

Here is the code:

//Sphere.cc

#include "Sphere.hh"

#include <float.h>

#include <cuda.h>

#include <cuda_runtime_api.h>

#include <vector_types.h>

#include <vector_functions.h>

__global__ void intersect(float *a,double radius, Vec3d direction, Vec3d origin, Vec3d center)

{

		a[0]=0.0;

		 Vec3d roc =(origin-center);

	 // | compute scalar product with another vector of same type (siehe VectorT.hh);

	 double z= -(roc|direction);

		 //pow returns base raised to the power exponent:

	 double d= pow( -z, 2.0)-((roc|roc) - (radius*radius));

	 

	if(d>0.0){

	  if((z-sqrt(d))>1e-5)

	 {

		 a[0]=1.0;

	 }

		 }

		else

	 a[0]=0.0;

}

bool

Sphere::

intersect(const Scene::Ray& _ray,

		  Vec3d&	 _intersection,

		  Vec3d&	 _normal,

		  double&	 _t ) const

{

		const int bla =1;

   		float *a_h, *a_d;

				size_t size = bla * sizeof(float);

				a_h = (float *)malloc(size);		// Allocate array on host

		  cudaMalloc((void **) &a_d, size);   // Allocate array on device

		  // Initialize host array and copy it to CUDA device

		  for (int i=0; i<bla; i++) a_h[i] = (float)i;

 		 cudaMemcpy(a_d, a_h, size, cudaMemcpyHostToDevice);

				

		dim3 block(8);

		dim3 grid(8);

		intersect<<<grid,block>>>(a_d,radius,_ray.direction,_ray.origin,center);

				cudaMemcpy(a_h, a_d, sizeof(float)*bla, cudaMemcpyDeviceToHost);

				if(a_h[0]==1.0){

			return true;

				}

		else return false;

				//free(a_h); 

				cudaFree(a_d);

}

The problem is, that the compiler dosnt acept the intersect<<<grid,block>>>(a_d,radius,_ray.direction,_ray.origin,center); line.

Do you know, how to solve this?

Here the output from the commandline:

[i]

g++ -I/usr/local/cuda/include -Wall -O3 -funroll-loops -DNDEBUG -fopenmp -MMD -MF release/Mesh.d -c Mesh.cc -o release/Mesh.o

g++ -I/usr/local/cuda/include -Wall -O3 -funroll-loops -DNDEBUG -fopenmp -MMD -MF release/Scene.d -c Scene.cc -o release/Scene.o

g++ -I/usr/local/cuda/include -Wall -O3 -funroll-loops -DNDEBUG -fopenmp -MMD -MF release/Sphere.d -c Sphere.cc -o release/Sphere.o

Sphere.cc: In member function ‘virtual bool Sphere::intersect(const Scene::Ray&, Vec3d&, Vec3d&, double&) const’:

Sphere.cc:48: error: expected primary-expression before ‘<’ token

Sphere.cc:48: error: expected primary-expression before ‘>’ token

Sphere.cc:48: warning: left-hand operand of comma has no effect

Sphere.cc:48: warning: right-hand operand of comma has no effect

Sphere.cc:48: warning: right-hand operand of comma has no effect

Sphere.cc:48: warning: right-hand operand of comma has no effect

make[1]: *** [release/Sphere.o] Fehler 1

make[1]: Verlasse Verzeichnis ‘/home/swalter/Ubuntu One/cg/CG-exercises/src/05-RayTracing Cuda’

make: *** [rel] Fehler 2

[/i]

I have really no idea, how to fix this problem. I just started in the last days with Cuda an I only finished the nvidia exersises yet. But beacause its realy fun to work with cuda, I am triing to change some of my normal .cc files, to use cuda.

Iam glad about every hint or solution.

Thanks a lot!

NVCC expects that kernel code is contained in files with a .cu extension. If you rename it, it will correctly preprocess the kernel code and pass it off to the device compiler.

Thanks!

so, even if the other files ar all cc files, I can just rename it?

The problem is also, that I have a fixed make file, can I still use it, or do I have to change it?

Here is the makefile:

########

.PHONY : dbg rel clean

rel:

	$(MAKE) COMP=release build

dbg:

	$(MAKE) COMP=debug build

	

clean:

	rm -rf $(CLEAN)

############

FRAMEWORKS_DIR := ../../Frameworks

CLEAN := ./debug ./release

INC := -I/usr/local/cuda/include

SRC := Mesh.cc Scene.cc Sphere.cc raytrace.cc 

DIR := ./$(COMP)

OBJ := $(addprefix $(DIR)/,$(SRC:.cc=.o))

EXE := $(DIR)/raytrace

################

# compiler options: release or debug

ifeq ($(COMP),release)

  CCOPTS  := -Wall -O3 -funroll-loops -DNDEBUG -fopenmp

else

  CCOPTS  := -Wall -g -fopenmp

endif

# which operating system?

OS := $(shell uname)

# Linux settings

ifeq ($(OS),Linux)

  CC := g++

  LDOPTS += -lgomp -lglut -lGLU -lGL -ljpeg -lcuda

  INC += 

  #INC += -I/home/swalter/NVIDIA_CUDA_SDK/common/inc

# unknown operating system

else

  $(error Operating system not defined)

endif

##############

$(DIR):

	test -d $(DIR) || mkdir -p $(DIR)

$(EXE): $(OBJ)

	$(CC) -o $@ $(OBJ) $(LDOPTS)

#################

$(DIR)/%.o : %.cc

	$(CC) $(INC) $(CCOPTS) -MMD -MF $(@:.o=.d) -c $< -o $@

################

# include dependency files

-include $(OBJ:.o=.d)

#include /home/swalter/NVIDIA_CUDA_SDK/common/common.mk

#TOP			  = $/usr/local/cuda/

#LD_LIBRARY_PATH += $(TOP)/lib:$(TOP)/extools/lib:

#PATH			+= $(TOP)/open64/bin:$(TOP)/bin:

#INCLUDES		+=  "-I$(TOP)/include" "-I$(TOP)/include/cudart" $(_SPACE_)

#LIBRARIES		=+ $(_SPACE_) "-L$(TOP)/lib" -lcudart

#CUDAFE_FLAGS	+=

#OPENCC_FLAGS	+=

#PTXAS_FLAGS	 +=

###############
ifeq ($(OS),Linux)

  CC := g++

  LDOPTS += -lgomp -lglut -lGLU -lGL -ljpeg -lcuda

  INC +=

couldnt I do the same for a cu ending?

But Iam actually not sure how do do it…

could I write something like this?

CU:=/usr/local/cuda/bin/nvcc

 LDOPTS += -lgomp -lglut -lGLU -lGL -ljpeg -lcuda

The problem is, the other files of the project should work as well, thats why I need a Makefile.

You must use nvcc to compile source containing CUDA code. You will need to define a rule for compiling the .cu file to an object file. Something like this;

%.o : %.cu

	$(NVCC) $(INC) $(CCOPTS)  -c $< -o $@

You will need to define NVCC and sort out source and destination paths yourself, but that is the basic idea. It should be fine to link all the objects with gcc as long as you link the necessary cuda libraries (which it looks like you already are).

ok, I tried it, but Iam sure its wrong, because it doesnt work :-D

FRAMEWORKS_DIR := ../../Frameworks

CLEAN := ./debug ./release

INC := -I/usr/local/cuda/include

SRC := Mesh.cc Scene.cc Sphere.cu raytrace.cc 

DIR := ./$(COMP)

OBJ := $(addprefix $(DIR)/,$(SRC:.cc=.o))

EXE := $(DIR)/raytrace

##############

# compiler options: release or debug

ifeq ($(COMP),release)

  CCOPTS  := -Wall -O3 -funroll-loops -DNDEBUG -fopenmp

else

  CCOPTS  := -Wall -g -fopenmp

endif

# which operating system?

OS := $(shell uname)

ifeq ($(OS),Linux)

  CC := g++

  LDOPTS += -lgomp -lglut -lGLU -lGL -ljpeg -lcuda

  INC += 

  NVCC := /usr/local/cuda/bin/nvcc

# unknown operating system

else

  $(error Operating system not defined)

endif

####################

ifeq ($(OS),Darwin)

build: $(DIR) Frameworks $(EXE)

else

build: $(DIR) $(EXE)

endif

$(DIR):

	test -d $(DIR) || mkdir -p $(DIR)

$(EXE): $(OBJ)

	$(CC) -o $@ $(OBJ) $(LDOPTS)

##########

$(DIR)/%.o : %.cu

	$(NVCC) $(INC) $(CCOPTS)  -c $< -o $@

$(DIR)/%.o : %.cc

	$(CC) $(INC) $(CCOPTS) -MMD -MF $(@:.o=.d) -c $< -o $@

#############

# include dependency files

-include $(OBJ:.o=.d)

I added the line

NVCC := /usr/local/cuda/bin/nvcc

and

$(DIR)/%.o : %.cu

	$(NVCC) $(INC) $(CCOPTS)  -c $< -o $@

If Iam using it, the following statment prints out:

[i]

$ make

Makefile:93: *** missing separator. Schluss.

[/i]

where line 93 is

$(DIR)/%.o : %.cu

	$(NVCC) $(INC) $(CCOPTS)  -c $< -o $@

Shouldnt I also add something like

OBJ += $(addprefix $(DIR)/,$(SRC:.cu=.o))

that the compiler knows, that cu files kann also be o files?

Thanks again for your help!

I hope, we can get this running :-)

That error usually means you are missing a tab somewhere. In gnu make separators must be tabs, not spaces. I am guessing it is the first line, but I don’t know which of the two is line 93. You might want to look at the gnu make info documentation if you haven’t already done so - it describes in detail how makefile statements must be formatted.

you were right, the space in front of the second line, the one with

$(NVCC) $(INC) $(CCOPTS)  -c $< -o $@

wasnt a tab. Now it is a tab. There is still another Problem, but I will try it first by myself, if it dosnt work out, I hope I can write you.

No i havent, but I will now :rolleyes:

Thanks!

because now, the compiler has again something with a missing seperator :teehee:

But now, its not in the make file, but in the file I want to compile

#include "Sphere.hh"

#include <float.h>

#include <cuda.h>

__global__ void intersect(float *a,double radius, Vec3d direction, Vec3d origin, Vec3d center){

	a[0]=0.0;

		Vec3d roc =(origin-center);

	 // | compute scalar product with another vector of same type (siehe VectorT.hh);

	double z= -(roc|direction);

		 //pow returns base raised to the power exponent:

	double d= pow( -z, 2.0)-((roc|roc) - (radius*radius));

	 

	if(d>0.0){

	  if((z-sqrt(d))>1e-5)

	 {

		 a[0]=1.0;

	 }

		 }

		else

	 a[0]=0.0;

}

and the compiler tells me

[i]

$ make

Sphere.cu:5: *** missing separator. Schluss.

[/i]

whre line 5 is

__global__ void intersect(float *a,double radius, Vec3d direction, Vec3d origin, Vec3d center){

funny thing, one missing seperator gone, another one appears :teehee: :sweat:

I think you still have a makefile problem. The code snippet you posted will compile with nvcc (forgive the liberties I had to take with it to get it to build without the include file),

avid@cuda:~$ cat bm.cu 

#include <float.h>

#include <cuda.h>

typedef float Vec3d;

__global__ void intersect(float *a,double radius, Vec3d direction, Vec3d origin, Vec3d center){

	a[0]=0.0;

		Vec3d roc =(origin-center);

	 // | compute scalar product with another vector of same type (siehe VectorT.hh);

	// double z= -(roc|direction);

	double z= 1.;

		 //pow returns base raised to the power exponent:

	// double d= pow( -z, 2.0)-((roc|roc) - (radius*radius));

	double d= 2.;

	

	if(d>0.0){

	  if((z-sqrt(d))>1e-5)

	 {

		 a[0]=1.0;

	 }

		 }

		else

	 a[0]=0.0;

}

avid@cuda:~$ nvcc -c bm.cu 

bm.cu(8): warning: variable "roc" was declared but never referenced

bm.cu(8): warning: variable "roc" was declared but never referenced

The error still looks like you are trying to compile CUDA code with gcc.

then I will work again on my makefile :-)

So, I stil didnt get it to work,

but I found out something interesting:

The error message

[i]

Sphere.cu:5: *** missing separator. Schluss.

[/i]

only appears, if I actually use Sphere.cu

If I write Sphere.cc in the Makefile

[i]

SRC := Mesh.cc Scene.cc Sphere.cc raytrace.cc

[/i]

this message wont come.

I hope, tomorrow, Ill get this problem fixed.

I gave it a last try for tonight.
This time, I load the Makefile up.

If I use it, Ill get the following outlines:

rm -rf ./debug ./release
make COMP=release build
make[1]: Betrete Verzeichnis ‘/home/swalter/Ubuntu One/cg/CG-exercises/src/05-RayTracing Cuda’
test -d ./release || mkdir -p ./release
g++ -I/usr/local/cuda/include -Wall -O3 -funroll-loops -DNDEBUG -fopenmp -MMD -MF release/Mesh.d -c Mesh.cc -o release/Mesh.o
g++ -I/usr/local/cuda/include -Wall -O3 -funroll-loops -DNDEBUG -fopenmp -MMD -MF release/Scene.d -c Scene.cc -o release/Scene.o
g++ -I/usr/local/cuda/include -Wall -O3 -funroll-loops -DNDEBUG -fopenmp -MMD -MF release/raytrace.d -c raytrace.cc -o release/raytrace.o
make[1]: *** Keine Regel vorhanden, um das Target »release/Sphere.o«,
benötigt von »release/raytrace«, zu erstellen. Schluss.
make[1]: Verlasse Verzeichnis ‘/home/swalter/Ubuntu One/cg/CG-exercises/src/05-RayTracing Cuda’
make: *** [rel] Fehler 2

So it actually says, that the compiler has no rule to build the »release/Sphere.o«

ok,

it looks like the upload didnt work.

####################

.PHONY : dbg rel clean

rel:

	$(MAKE) COMP=release build

dbg:

	$(MAKE) COMP=debug build

	

clean:

	rm -rf $(CLEAN)

#######################

FRAMEWORKS_DIR := ../../Frameworks

CLEAN := ./debug ./release

INC := -I/usr/local/cuda/include

SRC := Mesh.cc Scene.cc raytrace.cc

SRC1 := Sphere.cu

DIR := ./$(COMP)

OBJ := $(addprefix $(DIR)/,$(SRC:.cc=.o))

OBJ += $(addprefix $(DIR)/,$(SRC1:.cu=.o))

EXE := $(DIR)/raytrace

##################

# compiler options: release or debug

ifeq ($(COMP),release)

  CCOPTS  := -Wall -O3 -funroll-loops -DNDEBUG -fopenmp

else

  CCOPTS  := -Wall -g -fopenmp

endif

# which operating system?

OS := $(shell uname)

# MacOS settings

ifeq ($(OS),Darwin)

  CC := g++-4.2

	INC += -I../../Frameworks/libjpeg.framework/Headers

  LDOPTS += -F../../Frameworks -framework libjpeg -lgomp -framework OpenGL -framework GLUT

	CLEAN += ./Frameworks

 NVCC := nvcc

# Linux settings

else ifeq ($(OS),Linux)

  CC := g++

  LDOPTS += -lgomp -lglut -lGLU -lGL -ljpeg

# unknown operating system

else

  $(error Operating system not defined)

endif

####################

ifeq ($(OS),Darwin)

build: $(DIR) Frameworks $(EXE)

else

build: $(DIR) $(EXE)

endif

$(DIR):

	test -d $(DIR) || mkdir -p $(DIR)

# MacOS: install frameworks

ifeq ($(OS),Darwin)

Frameworks:

	cp -r $(FRAMEWORKS_DIR) .

endif

$(EXE): $(OBJ)

	$(CC) -o $@ $(OBJ) $(LDOPTS)

	$(NVCC) -o $@ $(OBJ) $(LDOPTS)

##################

$(DIR)/%cu.o : %.cu

	$(NVCC) $(INC) -c $< -o $@

$(DIR)/%.o : %.cc

	$(CC) $(INC) $(CCOPTS) -MMD -MF $(@:.o=.d) -c $< -o $@

######################

# include dependency files

-include $(OBJ:.o=.d)

#####################

I think your answer probably lies there.

?

I did somethink like this

INC := -I/usr/local/cuda/include

SRC := Mesh.cc Scene.cc raytrace.cc

SRC1 := Sphere.cu

DIR := ./$(COMP)

OBJ := $(addprefix $(DIR)/,$(SRC:.cc=.o))

OBJ += $(addprefix $(DIR)/,$(SRC1:.cu=.o))

The problem now is that you don’t have a compilation rule for Sphere.o. Neither of these two rules

$(DIR)/%cu.o : %.cu

	$(NVCC) $(INC) -c $< -o $@

$(DIR)/%.o : %.cc

	$(CC) $(INC) $(CCOPTS) -MMD -MF $(@:.o=.d) -c $< -o $@

will match Sphere.o by compiling from Sphere.cu. The first one matches Sphere.cu.o by compiling Sphere.cu, and the second Sphere.o by compiling Sphere.cc .

I think you really ought to spend a bit more time understanding how GNU make works. This really has nothing to do with CUDA, per se.

ok.

Thanks!