繁体   English   中英

makefile:cpp + cu files - 未定义引用的错误

[英]makefile: cpp + cu files - error of undefined reference

考虑三个文件:main.cpp,func_prototypes.h和test_kernels.cu。 我想从这三个文件中构建一个项目。 我试图基于CUDA样本来构建'makefile',但是我失败了。 make的执行返回未定义引用的错误。 在下文中,有我的三个文件和makefile

main.cpp中

#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;

}

func_prototypes.h

template <class type>
void getSquares(type *v, unsigned const int N);
void ResetCUDA();

test_kernels.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

返回的错误是main.o:main.cpp:function main: error: undefined reference to 'void getSquares<float>(float*, unsigned int)' make: *** [test] Error 1

有谁知道我的错误在哪里?

编辑:为了记录,我的操作系统是Ubuntu 12.04 x86_64,内核3.2.0-39

这是模板编译中标准问题的体现。

您的主机函数getSquares和内核getSquareKernel从未在定义它们的编译单元中实例化(即在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);

到test_kernels.cu的底部。 这将确保链接时存在您需要链接的设备和主机代码实例。

另一种方法是将包含main的文件更改为.cu文件,并将test_kernels.cu包含到该文件中,并使用nvcc编译整个文件。 在这种情况下, main()中的主机类的实例化应该触发在同一编译单元内编译完整的模板链。

免责声明:我没有在我面前的机器,我可以在此测试任何机器,所以至少代码的警告;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM