cuda - 具有不同输入的大型内核的智能设计,仅更改一行代码
问题描述
我正在设计一些内核,我希望有两种调用方式:一次使用标准float *
设备作为输入(用于编写),另一种使用cudaSurfaceObject_t
作为输入(用于编写)。内核本身很长(> 200 行),最终,我只需要最后一行不同。在一种情况下,您有标准out[idx]=val
类型的分配,而在另一种情况下,您有一种surf3Dwrite()
类型。内核的其余部分是相同的。
就像是
__global__ kernel(float * out , ....)
{
// 200 lines of math
// only difference, aside from input argument
idx=....
out[idx]=a;
}
对比
__global__ kernel(cudaSurfaceObject_t * out, ...)
{
// 200 lines of math
// only difference, aside from input argument
surf3Dwrite(&out,val,x,y,z);
}
没有复制粘贴整个内核并重命名它的聪明的编码方式是什么?我检查了模板,但是(如果我没记错的话)它仅用于类型,当模板中的类型不同时,不能只拥有完全不同的代码行。CUDA 内核似乎也无法重载。
解决方案
CUDA 内核似乎也无法重载。
应该可以重载内核。这是一种可能的方法,使用重载(并且没有模板):
$ cat t1648.cu
// Includes, system
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <helper_cuda.h>
__device__ float my_common(float *d, int width, unsigned int x, unsigned int y){
// 200 lines of common code...
return d[y *width +x];
}
////////////////////////////////////////////////////////////////////////////////
// Kernels
////////////////////////////////////////////////////////////////////////////////
//! Write to a cuArray using surface writes
//! @param gIData input data in global memory
////////////////////////////////////////////////////////////////////////////////
__global__ void WriteKernel(float *gIData, int width, int height,
cudaSurfaceObject_t outputSurface)
{
// calculate surface coordinates
unsigned int x = blockIdx.x*blockDim.x + threadIdx.x;
unsigned int y = blockIdx.y*blockDim.y + threadIdx.y;
// read from global memory and write to cuarray (via surface reference)
surf2Dwrite(my_common(gIData, width, x, y),
outputSurface, x*4, y, cudaBoundaryModeTrap);
}
__global__ void WriteKernel(float *gIData, int width, int height,
float *out)
{
// calculate coordinates
unsigned int x = blockIdx.x*blockDim.x + threadIdx.x;
unsigned int y = blockIdx.y*blockDim.y + threadIdx.y;
// read from global memory and write to global memory
out[y*width+x] = my_common(gIData, width, x, y);
}
////////////////////////////////////////////////////////////////////////////////
// Program main
////////////////////////////////////////////////////////////////////////////////
int main(int argc, char **argv)
{
printf("starting...\n");
unsigned width = 256;
unsigned height = 256;
unsigned int size = width * height * sizeof(float);
// Allocate device memory for result
float *dData = NULL;
checkCudaErrors(cudaMalloc((void **) &dData, size));
// Allocate array and copy image data
cudaChannelFormatDesc channelDesc =
cudaCreateChannelDesc(32, 0, 0, 0, cudaChannelFormatKindFloat);
cudaArray *cuArray;
float *out;
cudaMalloc(&out, size);
checkCudaErrors(cudaMallocArray(&cuArray,
&channelDesc,
width,
height,
cudaArraySurfaceLoadStore));
dim3 dimBlock(8, 8, 1);
dim3 dimGrid(width / dimBlock.x, height / dimBlock.y, 1);
cudaSurfaceObject_t outputSurface;
cudaResourceDesc surfRes;
memset(&surfRes, 0, sizeof(cudaResourceDesc));
surfRes.resType = cudaResourceTypeArray;
surfRes.res.array.array = cuArray;
checkCudaErrors(cudaCreateSurfaceObject(&outputSurface, &surfRes));
WriteKernel<<<dimGrid, dimBlock>>>(dData, width, height, outputSurface);
WriteKernel<<<dimGrid, dimBlock>>>(dData, width, height, out);
checkCudaErrors(cudaDestroySurfaceObject(outputSurface));
checkCudaErrors(cudaFree(dData));
checkCudaErrors(cudaFreeArray(cuArray));
}
$ nvcc -I/usr/local/cuda/samples/common/inc t1648.cu -o t1648
$
上面的示例是从 simpleSurfaceWrite CUDA 示例代码中快速组合而成的。它并非旨在正常运行或“正确”运行。它旨在展示如何从代码结构的角度使用重载来解决既定目标。
推荐阅读
- python - 如何检查数据库中的多个列是否具有相同的值
- linux - 如何在 alpine linux 中获取 docker 架构,如 amd64、arm32v7?
- php - 如何在页面中嵌入 phpinfo() 而不影响该页面的 CSS 样式
- c - OMP 分析中的依赖关系
- wordpress - 将图像从 GitHub 上传到 WordPress 网站
- java - 如何忽略 Sonar 中的重复代码报告?
- docker - 通过卷在容器之间共享数据
- c++ - Visual Studio 2017 中的读取或写入访问冲突
- cassandra - Cassandra 在插入多个表时回滚
- vba - 共享文件时保留链接图像的 Powerpoint 代码