CUDA 中的函数模板不 link

Function templates in CUDA do not link

我想使用 CUDA 10.1(在 VisualStudio 2017,64 位)创建一个应用程序。为了灵活性,我想使用模板,因为像素类型和尺寸可能会有所不同。代码片段如下。 但不知何故它不编译并给出错误 LNK2019

unresolved external symbol "__declspec(dllimport) void __cdecl CUDA_gradient(float *,unsigned int *,float *,float *)" (__imp_??$CUDA_gradient@MM@@YAXPEAMPEAI00@Z) referenced in function "protected: virtual void __cdecl itk::CudaGradientImageFilter,float,float,class itk::CudaImage,3> >::GPUGenerateData(void)" (?GPUGenerateData@?$CudaGradientImageFilter@V?$CudaImage@M@itk@@MMV?$CudaImage@V?$CovariantVector@M@itk@@@2@@itk@@MEAAXXZ)

根据其他 CUDA 没有模板问题。

泛型编程中 CUDA 模板的注意事项和主要陷阱是什么?

我的cpp文件中调用的函数是:

#include "itkCudaGradientImageFilter.h"
#include "itkCudaGradientImageFilter.hcu"
// ...
template <typename TInputImage, typename TOperatorValueType, typename TOutputValueType, typename TOutputImageType>
void
CudaGradientImageFilter<TInputImage,
                       TOperatorValueType,
                       TOutputValueType,
                       TOutputImageType>
::GPUGenerateData()
{
    //...the InputPxelType and the InputImageDimension are aquired somewhere else.
    CUDA_gradient<InputPixelType, OutputValueType, InputImageDimension>(pin, outputSize, outputSpacing, pout);
    //...

}

我调用时结果没有改变:

CUDA_gradient<float, float, 3>(pin, outputSize, outputSpacing, pout);

我有一个 cuda 头文件 (.hcu)

#include "ImageFeaturesExport.h"

    template<typename TInputPixelType,
             typename TOutputValueType,
             unsigned int TImageDimension = 3>
    void
    ImageFeatures_EXPORT
    CUDA_gradient(
        TInputPixelType* dev_in,
        unsigned int* size,
        float* spacing,
        TOutputValueType* dev_out
    );

以及.cu文件中对应的函数:

#include "itkCudaGradientImageFilter.hcu"
#include "cuda.h"
#include "cuda_runtime.h"
#include "device_launch_parameters.h"

template<typename TInputPixelType,
         typename TOutputPixelType,
         unsigned int TImageDimension>
__global__
void
gradient_kernel(cudaTextureObject_t in, TOutputPixelType* grad)
{
    //...compute gradient
}

template<typename TInputPixelType, typename TOutputValueType, unsigned int TImageDimension>
void
CUDA_gradient(
    TInputPixelType* dev_in,
    unsigned int* size,
    float* spacing,
    TOutputValueType* dev_out)
{
    // prepare texture, copy memory,...

    gradient_kernel<TInputPixelType, TOutputValueType, TImageDimension><<< dimGrid, dimBlock >>> (texObj, dev_out);
    CUDA_CHECK_ERROR;

    // Clean up [...]
}

您有一个 link 错误。

首先请注意,您的 .cpp 和 .cu 文件是独立编译的。

所以 nvcc 无法知道 template-parameters 它必须编译函数 CUDA_gradient.

您可以通过将以下行添加到您的 .cu 文件来使其编译:

template void CUDA_gradient<float,float,3>(
    float* dev_in,
    unsigned int* size,
    float* spacing,
    float* dev_out);

当然这只允许使用这个确切的模板参数。 但是如果你知道一组可能的模板参数有一个很好的 copy-paste-replace-party 和你的 good.