绑定纹理有两种

从GPU申请内存
把数据从CPU复制到GPU
绑定纹理

gpu全局内存只支持单下标访问
比如判断素数的程序中, num[bid*bid THREAD_NUM tid] 
  1.   cudaMalloc((void**) &gpudata, sizeof(longTEST);    
  2.   cudaMemcpy(gpudata, data, sizeof(longTEST,cudaMemcpyHostToDevice);  
然后在核函数中就可以这样访问 num[bid*bid THREAD_NUM tid] 

GPU端线性存储器的使用说明
虽然CUDA的显存分配函数包括1D,2D和3D的形式,但均不支持多下标访问。对于1D线性空间采用 cudaMalloc进行分配和cudaMemcpy进行数据拷贝,其使用方式与分页内存的方式基本一致,当然添加了数据拷贝的方向的控制。还有个需要注意的地方主机和设备间数据交换会自动同步,而设备与设备间不会,需要使用cudaThreadSynchronize()。 但对于2D和3D则不同,以2D为例,分配的函数为cudaMallocPitch,由于它不支持双下标寻址也不支持二级指针,其实就是cudaMalloc的对齐形式,但数据访问方式有 大的改变,须采用标准访问形式,即: T* pElement = (T*)((char*)BaseAddress + Row * pitch) + Column; 注意指针BaseAddress仍为一级指针,本人测试过若将其声明为二级指针,按道理采用如下访问方式: T* pElement = (T*)((char*)*BaseAddress + Row * pitch) + Column 此方式在模拟条件下能得到正确结果,但实际设备上无法得到正确输出,这也表征了CUDA的线性存储器本质上与内存的不同。 cudaMemcpy2D是用于2D线性存储器的数据拷贝,函数原型为: cudaMemcpy2D( void* dst,size_t dpitch,const void* src,s ize_t spitch ,size_t width,size_t height,enum cudaMemcpyKind kind ) 这里需要特别注意width与pitch的区别,width是实际需要拷贝的数据宽度而pitch是2D线性存储空间分配时对齐的行宽,而当数据传递发生在设备与主机之间时, 主机 端pitch==width。 综上我们可以看到,CUDA下对二维线性空间的 访问是不提供多下标支持的,访问时依然是通过计算偏移量得到,不同的地方在于使用pitch对齐后 非常利于实 现coalesce访问。

patch的理解:

  C语言申请2维内存时,一般是连续存放的。a[y][x]存放在第y*widthofx*sizeof(元素)+x*sizeof(元素)个字节。但在cuda的global memory访问中,从256字节对齐的地址(addr=0, 256, 512, ...)开始的连续访问是最有效率的。 这样,为了提高内存访问的效率,有了cudaMallocPitch函数。 cudaMallocPitch函数分配的内存中,数组的每一行的第一个元素的开始地址都保证是对齐的。因为每行有多少个数据是不确定的widthofx*sizeof(元素)不一定是256的倍数。故此,为保证数组的每一行的第一个元素的开始地址对齐,cudaMallocPitch在分配内存时,每行会多分配一些字节,以保证widthofx*sizeof(元素)+多分配的字节是256的倍数(对齐)。这样,y*widthofx*sizeof(元素)+x*sizeof(元素)来计算a[y][x]的地址就不正确了。而应该是y*[widthofx*sizeof(元素)+多分配的字节]+x*sizeof(元素)。而函数中返回的pitch的值就是widthofx*sizeof(元素)+多分配的字节。

cudaMallocPitch两个函数的用法,先看看cudalibrary中如何定义的这两个函数:

cudaError_t cudaMallocPitch ( void **  devPtr,
size_t *  pitch,
size_t  width,
size_t  height  
)

Allocates at least widthInBytes * height bytes of linear memory on the device and returns in *devPtr a pointer to the allocated memory. The function may pad the allocation to ensure that corresponding pointers in any given row will continue to meet the alignment requirements for coalescing as the address is updated from row to row. The pitch returned in *pitch by cudaMallocPitch() is the width in bytes of the allocation. The intended usage of pitch is as a separate parameter of the allocation, used to compute addresses within the 2D array. Given the row and column of an array element of type T, the address is computed as:

T* pElement = (T*)((char*)BaseAddress + Row * pitch) + Column;

For allocations of 2D arrays, it is recommended that programmers consider performing pitch allocations using cudaMallocPitch(). Due to pitch alignment restrictions in the hardware, this is especially true if the application will be performing 2D memory copies between different regions of device memory (whether linear memory or CUDA arrays).

 

Parameters:
devPtr  - Pointer to allocated pitched device memory
pitch  - Pitch for allocation
width  - Requested pitched allocation width
height 

- Requested pitched allocation height

 

 

cudaError_t cudaMemcpy2D ( void *  dst,
size_t  dpitch,
const void *  src,
size_t  spitch,
size_t  width,
size_t  height,
enum cudaMemcpyKind  kind  
)

 

Copies a matrix (height rows of width bytes each) from the memory area pointed to by src to the memory area pointed to by dst, where kind is one ofcudaMemcpyHostToHost, cudaMemcpyHostToDevice, cudaMemcpyDeviceToHost, or cudaMemcpyDeviceToDevice, and specifies the direction of the copy. dpitch and spitch are the widths in memory in bytes of the 2D arrays pointed to by dst and src, including any padding added to the end of each row. The memory areas may not overlap. Calling cudaMemcpy2D() with dst and src pointers that do not match the direction of the copy results in an undefined behavior. cudaMemcpy2D() returns an error if dpitch or spitch is greater than the maximum allowed.

 

 

Parameters:
dst  - Destination memory address
dpitch  - Pitch of destination memory
src  - Source memory address
spitch  - Pitch of source memory
width  - Width of matrix transfer (columns in bytes)
height  - Height of matrix transfer (rows)
kind  - Type of transfer

 

由此,可以对这两个函数有个充分的认识。此外,cudaMallocPitch和cudaMemcpy2D,一般用于二维数组各维度size不是2的幂次方的问题。使用cudaMallocPitch()那么该数组的对齐、大小、起始址等就自动做好了,其返回的pitch就是真正分配给数组的size(往往大于其真正申请的大小)。



cudaMallocPitch((void**)(&dev_features), &fea_pitch, sizeof(unsigned char) * sfeaturesw, sfeaturesh);
cudaChannelFormatDesc feaDesc = cudaCreateChannelDesc<unsigned char>();
cudaMemcpy2D(dev_features, fea_pitch, sfeatures, sizeof(unsigned char) * sfeaturesw, sizeof(unsigned char) * sfeaturesw, sfeaturesh, cudaMemcpyHostToDevice);
cudaBindTexture2D(NULL, features2D, dev_features, feaDesc, sfeaturesw, sfeaturesh, fea_pitch);

--------------------------------------------------------------------------------
int sfeatures_size = sizeof(unsigned char) * sfeaturesw * sfeaturesh;
cudaChannelFormatDesc chDesc2 = cudaCreateChannelDesc<unsigned char>();
cudaMallocArray(&featuresArray, &chDesc2, sfeaturesw, sfeaturesh);
cudaMemcpyToArray( featuresArray, 0, 0, sfeatures, sfeatures_size, cudaMemcpyHostToDevice );
cudaBindTextureToArray( features2D, featuresArray);    
-------------------------------------------------------------------------------------
int grid_data_size = sizeof(float) * gridl;
cudaMalloc((void**)&dev_grid,grid_data_size);
cudaMemcpy(dev_grid,sgrid,grid_data_size,cudaMemcpyHostToDevice);
cudaBindTexture(0,gridData1D,dev_grid);

----------------------------------------------------------------------------------

cudaError_t cudaMemcpy2D ( void *  dst,
size_t  dpitch,
const void *  src,
size_t  spitch,
size_t  width,
size_t  height,
enum cudaMemcpyKind  kind  
)


cudaError_t cudaMallocPitch ( void **  devPtr,
size_t *  pitch,
size_t  width,
size_t  height  
)



对于一维纹理,不管是 Linear Memory还是使用 cudaMallocPitch的,都可以使用tex1Dfetch和tex1D
而对于二维纹理,不管是cudaArray还是 cudaMallocPitch都是使用tex2D
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
OpenGL PBO是OpenGL中的一个扩展,它允许通过在图形处理单元(GPU)上创建一个像素缓冲对象(PBO),将数据从CPU传输到GPU,然后可以使用这些数据在纹理中显示图像。 在使用PBO和YUV420p格式的纹理显示图像之前,我们需要将YUV420p格式的图像数据转换为适用于OpenGL纹理的格式。YUV420p是一种常见的视频图像格式,它包含一个与图像分辨率相同的Y分量(明亮度)和两个与图像分辨率的四分之一相同的UV分量(色度)。Y分量与图像分辨率相同,而UV分量的分辨率被降低以节省存储和传输带宽。 首先,我们需要创建一个纹理,并将它与PBO关联。然后,我们可以将YUV420p数据传输到PBO中。将数据传输到PBO的过程涉及到将Y、U和V分量的数据按照特定的布局传输到PBO中。我们可以使用glBufferData函数将数据传输到PBO。 接下来,我们需要将PBO中的数据绑定纹理,并对纹理进行设置以正确地显示图像。我们可以使用glBindTexture函数来绑定纹理,并使用glTexSubImage2D函数将PBO中的数据传输到纹理中。 最后,我们可以使用OpenGL的渲染管线将纹理中的图像显示在屏幕上。我们可以使用一个简单的顶点着色器和一个片段着色器将纹理中的图像转换为可视化的图像。 总结起来,使用OpenGL PBO和YUV420p纹理可以更高效地显示图像。通过将图像数据传输到PBO中,并将PBO与纹理关联,可以在GPU上进行图像处理和渲染,从而提高了图像显示的效率和性能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zlingh

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值