最近做项目,需要用GPU来加速程序,现在碰到非常棘手的问题,特此来发帖求助望高手指点!
原来的程序是用GPU进行MPEG解码,解码出来的NV12格式的视频数据先复制到主机中的页锁定内存,然后再从页锁定内存复制到主机的分页内存当中。(全程使用的驱动API)
而现在我是想把GPU中驱动API解码出来的NV12视频数据直接进行NV12----RGB的格式转换后再存入主机内存。
但NV12----RGB的cuda程序时我用运行API所写,而驱动API和运行API有着一个非常明显的区别,就是函数的参数类型不一样,驱动API的参数类型甚至都不是指针! 下面是具体的代码:
原来代码:
cuMemcpyDtoH(g_bFrameData, pDecodedFrame, (nDecodedPitch * nHeight * 3 / 2));
这个函数是将Device中的视频数据存储到分配好的页锁定主机内存中。几点疑问:
我们先来看cuMemcpyDtoH()的定义:
cuMemcpyDtoH ( void * dstHost,
CUdeviceptr srcDevice,
size_t ByteCount
)
g_bFrameData为 unsigned char* 类型, 而pDecodedFrame为 CUdeviceptr 类型。
CUdeviceptr 又为 unsigned int 类型得转定义,也就是说驱动API中的整形数据可以代表GPU中的一个地址?
修改后的代码:
cuMemcpyDtoD((pintermid, pDecodedFrame, (nDecodedPitch * nHeight * 3 / 2));
//仍然用驱动api所写,device to device的传输,printermid 保存我想要的NV12视频数据。
再看一下cuMemcpyDtoD()的定义:
cuMemcpyDtoD ( CUdeviceptr dstDevice,
CUdeviceptr srcDevice,
size_t ByteCount
)
因为源和目的指针都是CUdeviceptr 类型,虽然它们不是指针,我也不理解他们如何能当做指针用,我也只能依葫芦画瓢定义了一个 CUdeviceptr 类型的pintermid 来当做指针用。
好的,下面重点来了,我写的一个核函数如下:
global void CUDA_NV12_rgb(unsigned char * NV12_Data_1536,unsigned char out_data);
输入输出都是unsigned char 指针类型,而现在的情况是输入接口为 prntermid,它不是一个指针,仅仅是一个unsigned int 类型的变量,所以我不得不这样调用核函数:
CUDA_NV12_rgb<<<dimGrid,dimBlock>>>((unsigned char*)( &printermid) , out_data );
只能给 printermid 加一个地址符 并强制转换成 unsigned char* 类型。
但程序运行后倒不会出错,但是得到的视频却失真非常严重。(核函数已经验证过肯定没有错)。
我想知道我的问题到底出在哪里呢? 运行API到底如何才能通过驱动API得到一个正确的适合自己的指针呢? 还是两者根本不可混用?
驱动API解码出来的数据到底如何存储的呢? 其指针全部为 unsigned int 的整形,我进行(unsignedchar*)(&printermid)这种强制转换会不会使其数据丢失呢?