C++ makefile:cpp+;cu文件-未定义引用的错误
考虑三个文件:main.cpp、func_prototype.h和test_kernels.cu。我想从这三个文件中构建一个项目。我试图基于CUDA示例构建一个“makefile”,但失败了。执行make返回未定义引用的错误。下面是我的三个文件和makefile main.cppC++ makefile:cpp+;cu文件-未定义引用的错误,c++,cuda,makefile,C++,Cuda,Makefile,考虑三个文件:main.cpp、func_prototype.h和test_kernels.cu。我想从这三个文件中构建一个项目。我试图基于CUDA示例构建一个“makefile”,但失败了。执行make返回未定义引用的错误。下面是我的三个文件和makefile main.cpp #include <iostream> #include <cstdlib> #include <stdlib.h> #include <stdio.h> #incl
#include <iostream>
#include <cstdlib>
#include <stdlib.h>
#include <stdio.h>
#include <new>
#include <cuda.h>
using namespace std;
#include "func_prototypes.h"
typedef float mytype;
int main(){
mytype *vec;
unsigned int N = 1024;
vec = new mytype[N];
for(int i = 0; i < N; i++){
vec[i] = i;
}
cout << "Calling CUDA function.\n";
getSquares(vec,N);
cout << "result:\n";
for(int i = 0; i < N; i++){
cout << vec[i] << " ";
}
ResetCUDA();
return EXIT_SUCCESS;
}
返回的错误是main.o:main.cpp:function main:error:void getSquares(float*,unsigned int)的未定义引用
制造:**[测试]错误1
有人知道我的错误在哪里吗
编辑:我的操作系统是Ubuntu 12.04 x86_64,内核3.2.0-39这是模板内编译的一种表现 主机函数
getSquares
和内核getsquareskernel
从未在定义它们的编译单元中实例化(即在test_kernels.cu内部)。因此,编译器从不为getSquares
发出任何代码,链接失败
由于您在test_kernels.cu中使用的是主机代码/设备代码组合编译轨迹,因此正确的解决方案是显式实例化test_kernels.cu中需要的模板代码的所有变体,方法是添加如下内容:
template __global__ void getSquareKernel<float>(float *, unsigned int);
template void getSquares<float>(float *, unsigned int);
template\uuuu global\uuuuuu\void getSquareKernel(float*,unsigned int);
模板void getSquares(浮点*,无符号整数);
到test_kernels.cu的底部。这将确保您需要链接此的设备和主机代码实例在链接时都存在
另一种选择是将包含main的文件更改为.cu文件,并将test_kernels.cu包含到该文件中,然后使用nvcc编译整个文件。在这种情况下,main()
中主机类的实例化应该触发在同一编译单元中编译完整的模板链
免责声明:我面前没有一台可以在上面测试的机器,所以请注意emptor至少有代码…将函数和内核的显式实例化添加到.cu文件中是有效的!如果这解决了您的问题,您可以接受答案,这将标记该问题为答案,并将其从未回答列表中删除。
#include <cuda.h>
#include <new>
#define BlockSize 256
template <class type>
__global__
void getSquareKernel(type *v, unsigned const int N){
int tIdx = blockIdx.x*blockDim.x + threadIdx.x;
if(tIdx < N){
v[tIdx] *= v[tIdx];
}
}
template <class type>
void getSquares(type *v, unsigned const int N){
int threads = BlockSize;
int blocks = ceil(N/threads);
type *d_v;
cudaMalloc(&d_v,N*sizeof(type));
cudaMemcpy(d_v,v,N*sizeof(type),cudaMemcpyHostToDevice);
getSquareKernel<<<blocks,threads>>>(d_v,N);
cudaMemcpy(v,d_v,N*sizeof(type),cudaMemcpyDeviceToHost);
cudaFree(d_v);
}
void ResetCUDA(){
cudaDeviceReset();
}
############################# Makefile ##########################
CUDA_PATH ?= /usr/local/cuda-5.0
CUDA_INC_PATH ?= $(CUDA_PATH)/include
CUDA_BIN_PATH ?= $(CUDA_PATH)/bin
ifeq ($(OS_SIZE),32)
CUDA_LIB_PATH ?= $(CUDA_PATH)/lib
else
CUDA_LIB_PATH ?= $(CUDA_PATH)/lib64
endif
ifeq ($(OS_SIZE),32)
LDFLAGS := -L$(CUDA_LIB_PATH) -lcudart
CPPFLAGS := -m32
else
LDFLAGS := -L$(CUDA_LIB_PATH) -lcudart
CPPFLAGS := -m64
endif
# Debug build flags
ifeq ($(dbg),1)
CPPFLAGS += -g
NVCCFLAGS = -g -G
endif
INCLUDES := -I$(CUDA_INC_PATH) -I. -I.. -I../../common/inc
CPP = icpc
NVCC = $(CUDA_BIN_PATH)/nvcc
SOURCE = main.cpp
AUX = test_kernels.cu
all: test
test_kernels.o: $(AUX)
$(NVCC) $(NVCCFLAGS) -o test_kernels.o -c $(AUX) $(NVCCFLAGS) $(INCLUDES)
main.o: $(SOURCE)
$(CPP) $(CPPFLAGS) -o main.o -c $(SOURCE) $(CPPFLAGS) $(INCLUDES)
test: test_kernels.o main.o
$(CPP) -o test test_kernels.o main.o $(LDFLAGS)
run: test
./test
clean:
rm -rf test *.o
template __global__ void getSquareKernel<float>(float *, unsigned int);
template void getSquares<float>(float *, unsigned int);