gpt4 book ai didi

c++ - 如何从 2D 纹理中成功读取

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:32:53 25 4
gpt4 key购买 nike

我怎样才能:

  1. 将 cudaMallocPitch 浮点内存绑定(bind)到 2D 纹理引用
  2. 复制一些主机数据到设备上的二维数组
  3. 将一个添加到纹理引用并写入 a.) Pitch 二维数组或 b.) 写入线性内存数组
  4. 读回答案并展示。

下面是一个应该完成这个的代码。请注意,对于 NxN 数组大小,我的代码有效。对于 NxM,其中 N!=M,我的代码基本没问题(不是正确的结果)。如果你能解决这个问题,我将奖励你 1 个互联网(数量有限)。也许我疯了,但根据文档,这应该有效(而且它确实适用于方阵!)。附加代码应使用“nvcc whateveryoucallit.cu -o runit”运行。

感谢您的帮助!

#include<stdio.h>
#include<cuda.h>
#include<iostream>
#define height 16
#define width 11
#define BLOCKSIZE 16

using namespace std;

// Device Kernels

//Texture reference Declaration
texture<float,2> texRefEx;


__global__ void kernel_w_textures(float* devMPPtr, float * devMPtr, int pitch)
{
// Thread indexes
unsigned int idx = blockIdx.x*blockDim.x + threadIdx.x;
unsigned int idy = blockIdx.y*blockDim.y + threadIdx.y;

// Texutre Coordinates
float u=(idx)/float(width);
float v=(idy)/float(height);
devMPtr[idy*width+idx]=devMPPtr[idy*pitch/sizeof(float)+idx];
// Write Texture Contents to malloc array +1
devMPtr[idy*width+idx]= tex2D(texRefEx,u,v);//+1.0f;
}
int main()
{
// memory size
size_t memsize=height*width;
size_t offset;
float * data, // input from host
*h_out, // host space for output
*devMPPtr, // malloc Pitch ptr
*devMPtr; // malloc ptr

size_t pitch;

// Allocate space on the host
data=(float *)malloc(sizeof(float)*memsize);
h_out=(float *)malloc(sizeof(float)*memsize);


// Define data
for (int i = 0; i < height; i++)
for (int j=0; j < width; j++)
data[i*width+j]=float(j);

// Define the grid
dim3 grid((int)(width/BLOCKSIZE)+1,(int)(height/BLOCKSIZE)+1), threads(BLOCKSIZE,BLOCKSIZE);

// allocate Malloc Pitch
cudaMallocPitch((void**)&devMPPtr,&pitch, width * sizeof(float), height);

// Print the pitch
printf("The pitch is %d \n",pitch/sizeof(float));

// Texture Channel Description
//cudaChannelFormatDesc channelDesc = cudaCreateChannelDesc<float>();
cudaChannelFormatDesc channelDesc = cudaCreateChannelDesc(32,0,0,0,cudaChannelFormatKindFloat);

// Bind texture to pitch mem:
cudaBindTexture2D(&offset,&texRefEx,devMPPtr,&channelDesc,width,height,pitch);
cout << "My Description x is " << channelDesc.x << endl;
cout << "My Description y is " << channelDesc.y << endl;
cout << "My Description z is " << channelDesc.z << endl;
cout << "My Description w is " << channelDesc.w << endl;
cout << "My Description kind is " << channelDesc.f << endl;
cout << "Offset is " << offset << endl;

// Set mutable properties:
texRefEx.normalized=true;
texRefEx.addressMode[0]=cudaAddressModeWrap;
texRefEx.addressMode[1]=cudaAddressModeWrap;
texRefEx.filterMode= cudaFilterModePoint;

// Allocate cudaMalloc memory
cudaMalloc((void**)&devMPtr,memsize*sizeof(float));

// Read data from host to device
cudaMemcpy2D((void*)devMPPtr,pitch,(void*)data,sizeof(float)*width,
sizeof(float)*width,height,cudaMemcpyHostToDevice);

//Read back and check this memory
cudaMemcpy2D((void*)h_out,width*sizeof(float),(void*)devMPPtr,pitch,
sizeof(float)*width,height,cudaMemcpyDeviceToHost);

// Print the memory
for (int i=0; i<height; i++){
for (int j=0; j<width; j++){
printf("%2.2f ",h_out[i*width+j]);
}
cout << endl;
}

cout << "Done" << endl;
// Memory is fine...

kernel_w_textures<<<grid,threads>>>(devMPPtr, devMPtr, pitch);

// Copy back data to host
cudaMemcpy((void*)h_out,(void*)devMPtr,width*height*sizeof(float),cudaMemcpyDeviceToHost);


// Print the Result
cout << endl;
for (int i=0; i<height; i++){
for (int j=0; j<width; j++){
printf("%2.2f ",h_out[i*width+j]);
}
cout << endl;
}
cout << "Done" << endl;

return(0);
}

编辑 10 月 17 日:所以我仍然没有找到解决这个问题的方法。 Nvidia 对此保持沉默,似乎世界也是如此。我找到了使用共享内存的解决方法,但如果有人有纹理解决方案,我将非常高兴。

编辑 Octoboer 26:仍然没有解决方案,但如果有人知道的话,仍然对解决方案感兴趣。

编辑 7 月 26 日:哇,已经 9 个月了——而我一直都忽略了正确答案。诀窍是:

if ( idx < width  && idy < height){//.... code }

如前所述。感谢所有做出贡献的人!

最佳答案

这可能与您的 block 大小有关。在此代码中,您试图将一个 16x16 线程 block 写入一个 11x16 内存块。这意味着您的某些线程正在写入未分配的内存。这也解释了为什么您的 (16*M x 32*N) 测试有效:没有线程写入未分配的内存,因为您的维度是 16 的倍数。

解决这个问题的一个简单方法是这样的:

if ((x < width) && (y < height)) {
// write output
devMPtr[idy*width+idx]= tex2D(texRefEx,u,v);
}

在调用内核之前,您需要将高度和宽度传递给内核函数或将常量复制到卡片。

关于c++ - 如何从 2D 纹理中成功读取,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3835052/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com