skm*_*skm -1 c++ multithreading
问题陈述: 我必须连续处理从相机捕获的8百万像素图像。上面必须有几种图像处理算法,例如颜色插值,颜色转换等。这些操作在CPU上将花费很长时间。因此,我决定使用CUDA内核在GPU上执行这些操作。我已经编写了可工作的CUDA内核用于颜色转换。但是我仍然需要进一步提高性能。
基本上有两个计算时间:
source image从CPU 复制到GPU,反之亦然source imageGPU的处理当图像从CPU复制到GPU时...。同样,当在GPU上处理图像时,其他任何事情都不会发生。
我的想法:我想进行多线程处理,以便节省时间。我想在GPU上进行前一张图像的处理时捕获下一张图像。并且,当GPU完成前一个图像的处理时,下一个图像已经在那里,可以将其从CPU传输到GPU。
我需要什么:我对多线程世界完全陌生。我正在看一些教程和其他一些东西,以了解更多有关它的信息。因此,我正在寻找有关适当步骤和适当逻辑的一些建议。
我不确定您是否真的需要线程。CUDA能够允许主机和设备之间进行异步并发执行(无需使用多个CPU线程。)您要的是一种非常标准的“流水线”算法。它看起来像这样:
$ cat t832.cu
#include <stdio.h>
#define IMGSZ 8000000
// for this example, NUM_FRAMES must be less than 255
#define NUM_FRAMES 128
#define nTPB 256
#define nBLK 64
unsigned char cur_frame = 0;
unsigned char validated_frame = 0;
bool validate_image(unsigned char *img) {
validated_frame++;
for (int i = 0; i < IMGSZ; i++) if (img[i] != validated_frame) {printf("image validation failed at %d, was: %d, should be: %d\n",i, img[i], validated_frame); return false;}
return true;
}
void CUDART_CB my_callback(cudaStream_t stream, cudaError_t status, void* data) {
validate_image((unsigned char *)data);
}
bool capture_image(unsigned char *img){
for (int i = 0; i < IMGSZ; i++) img[i] = cur_frame;
if (++cur_frame == NUM_FRAMES) {cur_frame--; return true;}
return false;
}
__global__ void img_proc_kernel(unsigned char *img){
int idx = threadIdx.x + blockDim.x*blockIdx.x;
while(idx < IMGSZ){
img[idx]++;
idx += gridDim.x*blockDim.x;}
}
int main(){
// setup
bool done = false;
unsigned char *h_imgA, *h_imgB, *d_imgA, *d_imgB;
size_t dsize = IMGSZ*sizeof(unsigned char);
cudaHostAlloc(&h_imgA, dsize, cudaHostAllocDefault);
cudaHostAlloc(&h_imgB, dsize, cudaHostAllocDefault);
cudaMalloc(&d_imgA, dsize);
cudaMalloc(&d_imgB, dsize);
cudaStream_t st1, st2;
cudaStreamCreate(&st1); cudaStreamCreate(&st2);
unsigned char *cur = h_imgA;
unsigned char *d_cur = d_imgA;
unsigned char *nxt = h_imgB;
unsigned char *d_nxt = d_imgB;
cudaStream_t *curst = &st1;
cudaStream_t *nxtst = &st2;
done = capture_image(cur); // grabs a frame and puts it in cur
// enter main loop
while (!done){
cudaMemcpyAsync(d_cur, cur, dsize, cudaMemcpyHostToDevice, *curst); // send frame to device
img_proc_kernel<<<nBLK, nTPB, 0, *curst>>>(d_cur); // process frame
cudaMemcpyAsync(cur, d_cur, dsize, cudaMemcpyDeviceToHost, *curst);
// insert a cuda stream callback here to copy the cur frame to output
cudaStreamAddCallback(*curst, &my_callback, (void *)cur, 0);
cudaStreamSynchronize(*nxtst); // prevent overrun
done = capture_image(nxt); // capture nxt image while GPU is processing cur
unsigned char *tmp = cur;
cur = nxt;
nxt = tmp; // ping - pong
tmp = d_cur;
d_cur = d_nxt;
d_nxt = tmp;
cudaStream_t *st_tmp = curst;
curst = nxtst;
nxtst = st_tmp;
}
}
$ nvcc -o t832 t832.cu
$ cuda-memcheck ./t832
========= CUDA-MEMCHECK
========= ERROR SUMMARY: 0 errors
$
Run Code Online (Sandbox Code Playgroud)
有很多cuda示例代码可能也有帮助,例如simpleStreams,asyncAPI和simpleCallbacks
| 归档时间: |
|
| 查看次数: |
2690 次 |
| 最近记录: |