在下面的示例中,如何避免代码复制? C ++ / Cuda

时间:2018-11-01 12:31:48

标签: c++ templates cuda refactoring replication

编辑:此代码有效,但看起来有很多代码复制部分,我找不到解决此问题的方法。

在MatrixDevice类中,我想在kerne.cu中调用内核函数。 我将MatrixDevice类简化为仅显示此概念的实际用法。

从MatricDevice,我有一些函数可以将MatrixDevice与其他MatrixDevice或数字相加,这应该适用于不同类型,在此示例中,对于float和double,模板应该没有问题,但是我必须声明重载函数MatrixCudaOperations extern是因为我无法将.cu文件包含到.h / .cpp文件中。

matrixdevice.h

extern void MatrixCudaOperations(const float* a, const float* b, float* result, size_t rows, size_t cols, EOperation operation);
extern void MatrixCudaOperations(const float* a, float b, float* result, size_t rows, size_t cols, EOperation operation);
extern void MatrixCudaOperations(const double* a, const double* b, double* result, size_t rows, size_t cols, EOperation operation);
extern void MatrixCudaOperations(const double* a, double b, double* result, size_t rows, size_t cols, EOperation operation);


template<class T>
class MatrixDevice{

    T* data;
    size_t rows;
    size_t cols;

    MatrixDevice& Add(const MatrixDevice &other);
    MatrixDevice& Add(T &other);
};

//Operations with MatrixDevice
//Add MatrixDevice to this
template<class T>
MatrixDevice& MatrixDevice::Add(const MatrixDevice &other){
    MatrixCudaOperations(data, other.data, data, rows, cols, EOperation::ADD);
    return *this;
} 

//Add two MatrixDevice and return the result as new MatrixDevice
template<class T>
MatrixDevice Add(const MatrixDevice &a, const MatrixDevice &b){
    MatrixDevice result(a);
    result.Add(b);
    return result;
}

//Add two MatrixDevice to result MatrixDevice
template<class T>
void Add(const MatrixDevice &a, const MatrixDevice &b, MatrixDevice &result){
    MatrixCudaOperations(a.data, b.data, result.data, a.rows, a.cols, EOperation::ADD);
}


//Operations with Number

//Add T number to this
template<class T>
MatrixDevice& MatrixDevice::Add(T &other){
    MatrixCudaOperations(data, other, data, rows, cols, EOperation::ADD);
    return *this;
} 

//Add T number to MatrixDevice and return the result as new MatrixDevice
template<class T>
MatrixDevice Add(const MatrixDevice &a, T &b){
    MatrixDevice result(a);
    result.Add(b);
    return result;
}

//Add T number with MatrixDevice to result MatrixDevice
template<class T>
void Add(const MatrixDevice &a, T &b, MatrixDevice &result){
    MatrixCudaOperations(a.data, b, result.data, a.rows, a.cols, EOperation::ADD);
}

在内核中,我声明MatrixCudaOpertions的重载函数,并且任何函数中的代码都相同。 我使用模板进行了尝试,但是如果我需要在MatrixDevice类中进行外部声明的话,它将无法正常工作。

kernel.cu

template<class T> __global__
void d_Add(const T* a, const T* b, T* result){
    //code
}

template<class T> __global__
void d_Add(const T* a, T b, T* result){
    //code
}

void MatrixCudaOperations(const float* a, const float* b, float* result, size_t rows, size_t cols, EOperation operation){
    dim3 blocksize(rows, cols);

    switch(operation){
        case ADD:
            d_Add<<<1,blocksize>>>(a, b, result);
            break;
        //other cases, subtract, multiply...
    }
}

void MatrixCudaOperations(const float* a, float b, float* result, size_t rows, size_t cols, EOperation operation){
    dim3 blocksize(rows, cols);

    switch(operation){
        case ADD:
            d_Add<<<1,blocksize>>>(a, b, result);
            break;
        //other cases, subtract, multiply...
    }
}

void MatrixCudaOperations(const double* a, const double* b, double* result, size_t rows, size_t cols, EOperation operation){
    dim3 blocksize(rows, cols);

    switch(operation){
        case ADD:
            d_Add<<<1,blocksize>>>(a, b, result);
            break;
        //other cases, subtract, multiply...
    }
}

void MatrixCudaOperations(const double* a, double b, double* result, size_t rows, size_t cols, EOperation operation){
    dim3 blocksize(rows, cols);

    switch(operation){
        case ADD:
            d_Add<<<1,blocksize>>>(a, b, result);
            break;
        //other cases, subtract, multiply...
    }
}

1 个答案:

答案 0 :(得分:1)

从顶部开始。

template<class T>
class MatrixDevice;

template<class T>
static T const& to_matrix_data( T const& t ) { return t; }
template<class T>
static T const* to_matrix_data( MatrixDevice<T> const& m ) { return m.data; }

template<class T, class Rhs>
void AddInto(MatrixDevice<T>& target, MatrixDevice<T> const& src, Rhs const& rhs) {
  MatrixCudaOperations(src.data, to_matrix_data<T>(rhs), target.data, EOperation::ADD );
}

template<class T>
class MatrixDevice{
  T* data;
  size_t rows;
  size_t cols;

  template<class Rhs>
  MatrixDevice& +=(const Rhs &other)& {
    AddInto( *this, *this, other );
    return *this;
  }

  template<class Rhs>
  friend MatrixDevice operator+(MatrixDevice lhs, Rhs const& rhs) {
    lhs += rhs;
    return lhs;
  }
};

对三个不同的操作使用单词Add是不好的。一个是递增,另一个是加,最后一个是加。

因此,我编写了一个免费的模板函数AddInto。然后根据增量进行添加。

我的添加费用最多比您多,而根据矩阵的内部结构,此举是免费的。