[gelöst] Erste Schritte mit CUDA - Compilerfehler
-
Hallo allerseits,
ich setze mich gerade mit CUDA auseinander und verzweifel langsam.
Mein erstes Programm soll einfach zwei Vektoren mit jeweils n Elementen addieren und in einen dritten schreiben.
Der Quelltext ist in zwei Dateien aufgeteilt: zum Einen die main.cpp und die kernel_vector_add.cu. Die Quelltexte sind unten aufgelistet.
Zum compilieren habe ich mittlerweile zwei Makefiles erzeugt, die beide die identischen Fehlermeldungen produzieren. Auch diese sind unten aufgelistet.
Makefile 1 greift das aus den Beispielprojekten bekannte Schema auf. Es werden einfach die zu compilierenden Dateien registriert und die includierte common.mk übernimmt den Rest. Bei der zweiten Makefile wird alles händisch erzeugt.Kommen wir zum Wesentlichen. Die Fehlermeldung ist hier unten aufgelistet. Mich irritiert, dass er die angegebenen Variablen nicht finden kann, obwohl die doch eigentlich systemweit verfügbar sein müssten.
nvcc -c main.cpp -I. -I/usr/local/cuda/include -I/Developer/GPU\ Computing/C/common/inc In file included from main.cpp:3: kernel_vector_add.cu: In function ‘void VecAdd(float*, float*, float*, int)’: kernel_vector_add.cu:8: error: ‘blockDim’ was not declared in this scope kernel_vector_add.cu:8: error: ‘blockIdx’ was not declared in this scope kernel_vector_add.cu:8: error: ‘threadIdx’ was not declared in this scope main.cpp: In function ‘int main(int, char**)’: main.cpp:29: error: invalid conversion from ‘float**’ to ‘void**’ main.cpp:29: error: initializing argument 1 of ‘cudaError_t cudaMalloc(void**, size_t)’ main.cpp:30: error: invalid conversion from ‘float**’ to ‘void**’ main.cpp:30: error: initializing argument 1 of ‘cudaError_t cudaMalloc(void**, size_t)’ main.cpp:31: error: invalid conversion from ‘float**’ to ‘void**’ main.cpp:31: error: initializing argument 1 of ‘cudaError_t cudaMalloc(void**, size_t)’ main.cpp:36: error: expected primary-expression before ‘<’ token main.cpp:36: error: expected primary-expression before ‘>’ token make: *** [main.o] Error 1Das CUDA-SDK ist soweit installiert und compiliert und die Beispielprogramme laufen auch korrekt. Insofern liegt das Problem bei mir und meiner Makefile.
Ich bitte euch um eure Hilfe, weil ich absolut nicht mehr weiter weiß.
Beste Grüße
Vic
PS:
Ich entwickel auf einem Mac mit der gcc Version 4.2.1.
Die CUDA Bibliothek liegt in der Version 3.2 vor.#include <stdio.h> #include <cuda.h> #include "kernel_vector_add.cu" #include <cutil_inline.h> int main (int argc, char** argv) { const unsigned int numElements = 100; const unsigned int vecByteSize = numElements * sizeof(float); unsigned int i = 0; const int threadsPerBlock = 50; const int blocksPerGrid = (numElements + threadsPerBlock - 1) / threadsPerBlock; float* vecA = (float*)malloc(vecByteSize); float* vecB = (float*)malloc(vecByteSize); float* vecC = (float*)malloc(vecByteSize); for (i = 0; i < numElements; ++i) { vecA[i] = i; vecB[i] = i; vecC[i] = 0; } float* dA = 0; float* dB = 0; float* dC = 0; cudaMalloc(&dA, vecByteSize); cudaMalloc(&dB, vecByteSize); cudaMalloc(&dC, vecByteSize); cudaMemcpy(dA, vecA, vecByteSize, cudaMemcpyHostToDevice); cudaMemcpy(dB, vecB, vecByteSize, cudaMemcpyHostToDevice); VecAdd<<<blocksPerGrid, threadsPerBlock>>>(dA, dB, dC, numElements); cudaThreadSynchronize(); cudaMemcpy(vecC, dC, vecByteSize, cudaMemcpyDeviceToHost); cudaFree(dA); cudaFree(dB); cudaFree(dC); free(vecA); free(vecB); free(vecC); return 0; }#ifndef __KERNEL_VECTOR_ADD_CU__ #define __KERNEL_VECTOR_ADD_CU__ #include <cuda.h> #include <cutil_inline.h> __global__ void VecAdd (float *A, float *B, float *C, int numElements) { const int i = blockDim.x * blockIdx.x + threadIdx.x; if (i < numElements) { C[i] = A[i] + B[i]; } } #endif# Makefile 1 BINDIR := ./ EXECUTABLE := vecAddSample CCFILES := CUFILES := vectorAdd.cu ROOTDIR := /Developer/GPU\ Computing/C/common include $(ROOTDIR)/../common/common.mk# Makefile 2 PROJECT=VecAdd CC=g++ NVCC=nvcc WARNINGS=#-Wall INCDIR=-I. -I/usr/local/cuda/include -I/Developer/GPU\ Computing/C/common/inc LIBDIR=-L/usr/local/cuda/lib CUFILES=kernel_vector_add.cu LIBS=-lcublas -lcuda -lcudart -lcufft -lcurand -lcusparse -ltlshook OBJ=main.o kernel_vector_add.cu.o $(PROJECT) : $(OBJ) $(NVCC) -o $(PROJECT) $(OBJ) $(LIBDIR) $(LIBS) kernel_vector_add.cu.o : kernel_vector_add.cu $(NVCC) -c kernel_vector_add.cu -o kernel_vector_add.cu.o $(INCDIR) main.o : main.cpp $(NVCC) -c main.cpp $(WARNINGS) $(INCDIR)
-
OK. Ich habe mir die Beispieldateien nochmal genau angeguckt und bin (endlich) von allein auf die Lösung gekommen. Die möchte ich allen Anfängern natürlich nicht vorenthalten.
Mein erstes Problem war, dass ich C++ und C Code in der main.cpp gemixt habe. CUDA will aber wohl nur reinen C Code sehen. Deshalb habe ich eine Schnittstellenklasse angelegt, in der ich die C-Funktionen, die ich vom C++ Teil aufrufe, exportiere.
Eine weitere Besonderheit ist, dass ihr nicht die kernel_vector_add Objektdatei linken dürft, da ihr sonst eine Fehlermeldung erhaltet, die sich über "duplicate symbol XXXVecAdd_KernelXXX" beschwert.Summa summarum kommen die folgenden Dateien bei raus.
Makefile
PROJECT=VecAdd CC=g++ NVCC=nvcc WARNINGS=#-Wall INCDIR=-I. -I/usr/local/cuda/include -I/Developer/GPU\ Computing/C/common/inc LIBDIR=-L/usr/local/cuda/lib LIBS=-lcublas -lcuda -lcudart -lcufft -ltlshook OBJ=main.o cpp_kernel_interface.cu.o $(PROJECT) : $(OBJ) $(NVCC) -o $(PROJECT) $(OBJ) $(LIBDIR) $(LIBS) cpp_kernel_interface.cu.o : cpp_kernel_interface.cu $(NVCC) -c cpp_kernel_interface.cu -o cpp_kernel_interface.cu.o $(INCDIR) main.o : main.cpp $(NVCC) -c main.cpp $(WARNINGS) $(INCDIR) -o main.omain.cpp
#include <iostream> extern "C" void VecAdd (float *A, float *B, float *C, int numElements); int main (int argc, char** argv) { const unsigned int numElements = 100; const unsigned int vecByteSize = numElements * sizeof(float); unsigned int i = 0; float* vecA = new float[vecByteSize]; float* vecB = new float[vecByteSize]; float* vecC = new float[vecByteSize]; for (i = 0; i < numElements; ++i) { vecA[i] = 1.0f * i; vecB[i] = 1.0f * i; vecC[i] = 0.0f; } VecAdd(vecA, vecB, vecC, numElements); for (i = 0; i < numElements; ++i) { std::cout << vecA[i] << " + " << vecB[i] << " = " << vecC[i] << std::endl; } delete vecA; delete vecB; delete vecC; return 0; }cpp_kernel_interface.cu
#ifndef __CPP_KERNEL_INTERFACE_CU__ #define __CPP_KERNEL_INTERFACE_CU__ #include <cuda.h> #include <cutil_inline.h> #include <kernel_vector_add.cu> extern "C" void VecAdd (float *A, float *B, float *C, int numElements) { unsigned int vecByteSize = numElements * sizeof(float); float* dA = 0; float* dB = 0; float* dC = 0; const int threadsPerBlock = 50; const int blocksPerGrid = (numElements + threadsPerBlock - 1) / threadsPerBlock; cudaMalloc((void**)&dA, vecByteSize); cudaMalloc((void**)&dB, vecByteSize); cudaMalloc((void**)&dC, vecByteSize); cudaMemcpy(dA, A, vecByteSize, cudaMemcpyHostToDevice); cudaMemcpy(dB, B, vecByteSize, cudaMemcpyHostToDevice); VecAdd_Kernel<<< blocksPerGrid, threadsPerBlock >>>(dA, dB, dC, numElements); cudaThreadSynchronize(); cudaMemcpy(C, dC, vecByteSize, cudaMemcpyDeviceToHost); cudaFree(dA); cudaFree(dB); cudaFree(dC); } #endifkernel_vector_add.cu
#ifndef __KERNEL_VECTOR_ADD_CU__ #define __KERNEL_VECTOR_ADD_CU__ #include <cuda.h> #include <cutil_inline.h> __global__ void VecAdd_Kernel (float *A, float *B, float *C, int numElements) { const int i = blockDim.x * blockIdx.x + threadIdx.x; if (i < numElements) { C[i] = A[i] + B[i]; } } #endif