Cuda:混合c ++和cuda代码

时间:2015-04-16 19:10:54

标签: c++ c++11 cuda

我的问题如下: 我想将cuda代码添加到已经存在的c ++库中,并尽可能地重用我现有的代码。 为了使用多态,我使用模板类和模板内核。因此,所有内容都以.cpp,.h和.cuh文件实现。不涉及.cu文件,因此不使用nvcc并且c ++编译器在<<<<<< >>>内核调用语法。

我已经看过了 [How to separate the kernel file CUDA with the main .cpp file和 [How to call a CUDA file from a C++ header file?但我找不到任何可以解决我问题的设计。

涉及的文件:

的main.cpp

实例化一堆我已经存在的类,将它们传递给组成它们的CudaPrepare类,并负责准备要传递给只有原始类型的cuda代码的数据。

#include "CudaPrepare.h"
#include "CudaSpecificType1.h"
#include "A.h" //already existing classes 
#include "B.h" //already existing classes

void main()
{
    A a(...);
    B b(...);
    CudaSpecificType1 cudaType(...);
    CudaPrepare<CudaSpecificType> cudaPrepare(a, b, cudaType);
    cudaPrepare.run();

}

CudaSpecificType1.cuh

class CudaSpecificType1
{
protected:
/*
a few members
*/
public:
CudaSpecificType1(...) : /*initializations*/ {}
float polymorphicFunction(/*args*/); 
};

CudaPrepare.h

#include "A.h" //already existing classes 
#include "B.h" //already existing classes

template<typename T>
class CudaPrepare
{
protected:
const A& a;
const B& b;
const T& t;
public:
CudaPrepare(const A& a, const B& b, const T& t): A(a), B(b), T(t) {/*some initialization stuff*/}
void run() const
{
/*
data preparation : various discretizations,  sticking to primitive type only, casting to single precision etc...
*/

CudaClass<T> cudaClass(t, /*all the prepared data here*/);
cudaClass.run();

}
};

CudaClass.cuh

template <typename T>
__global__ void kernel(const T t, /*other args*/, float* results)
{
int threadId = ...;
results[threadId] = t.polymorphicFunction(...);

}



template<typename T>
class CudaClass
{
protected:
const T& t;
/*
all the prepared data with primitive types
*/
public:
CudaClass(const T& t, ...) : t(t) /*other initialization*/ {}
void run() const
{
/*
grid size calculation, cuda memory allocation, data transfer to device...
*/
//kernel invocation
kernel<T><<</*grid & block size*/>>>(/*args*/);
/*
clean up with cudaFree(...);
*/
}
};

c ++编译器按预期在内核调用时给出错误。 CudaClass :: run()无法移动到.cu文件,因为该类是模板化的。 我唯一能想到的是引入一个.cu文件替换main.cpp /或包含一个将从main.cpp调用的存根, 但是后来nvcc无法处理一些c ++ 11的功能。特别是,A.h和B.h包含很多枚举类......

1 个答案:

答案 0 :(得分:0)

我用Cuda 7.0进行了实验(之前是6.5)。遗憾的是,似乎仍然没有(至少)以下c ++ 11功能的支持:

  1. 枚举类

  2. 最终关键字

  3. 基于循环的范围

  4. 然而,正如Robert Crovella所建议的,显式模板实例化解决了这个问题。

    CudaClass.cuh必须分为两部分:

    CudaClass.cuh

    template <typename T>
    __global__ void kernel(const T t, /*other args*/, float* results)
    {
    int threadId = ...;
    results[threadId] = t.polymorphicFunction(...);
    
    }
    
    
    
    template<typename T>
    class CudaClass
    {
    protected:
    const T& t;
    /*
    all the prepared data with primitive types
    */
    public:
    CudaClass(const T& t, ...) : t(t) /*other initialization*/ {}
    
    void run() const;
    
    };
    

    CudaClass.cu

    #include "CudaClass.cuh"
    
    
    
    //explicit instantiation, so that the kernel invocation can be in a .cu file
    template class CudaClass<CudaSpecificType1>;
    /*
    other explicit instantiations for various types
    */
    
    
    
    template<typename T>
    void run() const
    {
    /*
    grid size calculation, cuda memory allocation, data transfer to device...
    */
    //kernel invocation
    kernel<T><<</*grid & block size*/>>>(/*args*/);
    /*
    clean up with cudaFree(...);
    */
    }