读取设备代码中的cudaArray

读取设备代码中的cudaArray,cuda,textures,device,Cuda,Textures,Device,是否有一种方法可以从设备读取cudaArray中的值,而不必将其包装在纹理参考/对象中?我看过的所有示例都专门使用cudaArrays创建纹理。这是唯一可以使用它们的方法,还是我可以这样做: __global__ kernel(cudaArray *arr, ...) { float x = tex1D<float>(arr, ...); ... } cudaArray *arr; cudaMallocArray(&arr, ...); cudaMemcpy

是否有一种方法可以从设备读取
cudaArray
中的值,而不必将其包装在纹理参考/对象中?我看过的所有示例都专门使用
cudaArray
s创建纹理。这是唯一可以使用它们的方法,还是我可以这样做:

__global__ kernel(cudaArray *arr, ...) {
    float x = tex1D<float>(arr, ...);
    ...
}

cudaArray *arr;
cudaMallocArray(&arr, ...);
cudaMemcpyToArray(arr, ...);
kernel<<<...>>>(arr, ...);
\uuuuu全局内核(cudaArray*arr,…){
浮点数x=tex1D(arr,…);
...
}
cudaArray*arr;
Cudamalocarray(&arr,…);
cudaMemcpyToArray(arr,…);
内核(arr,…);
那么基本上,应该用什么来代替那里的
tex1D
?此外,如果这是可能的,我很好奇是否有人认为这样做会对性能有任何好处,但我也会运行自己的测试来看看


谢谢

cudaArray是为纹理或表面存储目的而定义的。如图所示:

CUDA阵列是为纹理提取而优化的不透明内存布局。 它们是一维、二维或三维和三维的 由元素组成,每个元素有1个、2个或4个可能 可以是有符号或无符号8位、16位或32位整数、16位浮点或32位浮点 钻头浮动。CUDA数组只能由内核通过纹理访问 按照纹理内存或曲面读写中的描述进行提取 如表面存储器中所述

所以实际上,您必须使用内核中的任何一个来访问cudaArray中的数据

使用纹理有多种性能优势可能性。纹理可以暗示插值(即使用浮点坐标从纹理读取)。任何需要这种数据插值的应用程序都可能受益于GPU纹理单元内的HW插值引擎


另一个好处,也许是在任意GPU代码中使用纹理最重要的好处,是纹理缓存,它可以备份存储在全局内存中的纹理。纹理是一种只读操作,但如果您有一组只读数据,纹理缓存可能会提高或扩展您快速访问数据的能力。这通常意味着在访问纹理机制中存储的数据的函数中必须有数据局部性/数据重用。检索到的纹理数据不会中断一级缓存中的任何内容,因此通常这种数据分割/优化将是围绕数据缓存的更大策略的一部分。如果对一级缓存没有其他要求,纹理机制/缓存不会提供比一级缓存中更快的数据访问速度。

cudaArray是为纹理或表面内存目的定义的。如图所示:

CUDA阵列是为纹理提取而优化的不透明内存布局。 它们是一维、二维或三维和三维的 由元素组成,每个元素有1个、2个或4个可能 可以是有符号或无符号8位、16位或32位整数、16位浮点或32位浮点 钻头浮动。CUDA数组只能由内核通过纹理访问 按照纹理内存或曲面读写中的描述进行提取 如表面存储器中所述

所以实际上,您必须使用内核中的任何一个来访问cudaArray中的数据

使用纹理有多种性能优势可能性。纹理可以暗示插值(即使用浮点坐标从纹理读取)。任何需要这种数据插值的应用程序都可能受益于GPU纹理单元内的HW插值引擎


另一个好处,也许是在任意GPU代码中使用纹理最重要的好处,是纹理缓存,它可以备份存储在全局内存中的纹理。纹理是一种只读操作,但如果您有一组只读数据,纹理缓存可能会提高或扩展您快速访问数据的能力。这通常意味着在访问纹理机制中存储的数据的函数中必须有数据局部性/数据重用。检索到的纹理数据不会中断一级缓存中的任何内容,因此通常这种数据分割/优化将是围绕数据缓存的更大策略的一部分。如果对一级缓存没有其他要求,纹理机制/缓存不会提供比一级缓存更快的数据访问速度。

Robert Crovella已经回答了您的问题。我相信对于下一个用户来说,为两个解决方案提供一个有效的示例可能会很有用:纹理和表面

#include <stdio.h>
#include <thrust\device_vector.h>

// --- 2D float texture
texture<float, cudaTextureType2D, cudaReadModeElementType> texRef;

// --- 2D surface memory
surface<void, 2> surf2D;

/********************/
/* CUDA ERROR CHECK */
/********************/
#define gpuErrchk(ans) { gpuAssert((ans), __FILE__, __LINE__); }
inline void gpuAssert(cudaError_t code, char *file, int line, bool abort=true)
{
    if (code != cudaSuccess) 
    {
        fprintf(stderr,"GPUassert: %s %s %d\n", cudaGetErrorString(code), file, line);
        if (abort) exit(code);
    }
}

/*************************************/
/* cudaArray PRINTOUT TEXTURE KERNEL */
/*************************************/
__global__ void cudaArrayPrintoutTexture(int width, int height)
{
    unsigned int x = blockIdx.x * blockDim.x + threadIdx.x;
    unsigned int y = blockIdx.y * blockDim.y + threadIdx.y;

    printf("Thread index: (%i, %i); cudaArray = %f\n", x, y, tex2D(texRef, x / (float)width + 0.5f, y / (float)height + 0.5f));
}

/*************************************/
/* cudaArray PRINTOUT TEXTURE KERNEL */
/*************************************/
__global__ void cudaArrayPrintoutSurface(int width, int height)
{
    unsigned int x = blockIdx.x * blockDim.x + threadIdx.x;
    unsigned int y = blockIdx.y * blockDim.y + threadIdx.y;

    float temp;

    surf2Dread(&temp, surf2D, x * 4, y);

    printf("Thread index: (%i, %i); cudaArray = %f\n", x, y, temp);
}

/********/
/* MAIN */
/********/
void main()
{
    int width = 3, height = 3;

    thrust::host_vector<float> h_data(width*height, 3.f);

    // --- Allocate CUDA array in device memory
    cudaChannelFormatDesc channelDesc = cudaCreateChannelDesc(32, 0, 0, 0, cudaChannelFormatKindFloat);

    cudaArray* cuArray;

    /*******************/
    /* TEXTURE BINDING */
    /*******************/
    gpuErrchk(cudaMallocArray(&cuArray, &channelDesc, width, height));

    // --- Copy to host data to device memory
    gpuErrchk(cudaMemcpyToArray(cuArray, 0, 0, thrust::raw_pointer_cast(h_data.data()), width*height*sizeof(float), cudaMemcpyHostToDevice));

    // --- Set texture parameters
    texRef.addressMode[0] = cudaAddressModeWrap;
    texRef.addressMode[1] = cudaAddressModeWrap;
    texRef.filterMode = cudaFilterModeLinear;
    texRef.normalized = true;

    // --- Bind the array to the texture reference
    gpuErrchk(cudaBindTextureToArray(texRef, cuArray, channelDesc));

    // --- Invoking printout kernel
    dim3 dimBlock(3, 3);
    dim3 dimGrid(1, 1);
    cudaArrayPrintoutTexture<<<dimGrid, dimBlock>>>(width, height);

    gpuErrchk(cudaUnbindTexture(texRef));

    gpuErrchk(cudaFreeArray(cuArray));

    /******************/
    /* SURFACE MEMORY */
    /******************/
    gpuErrchk(cudaMallocArray(&cuArray, &channelDesc, width, height, cudaArraySurfaceLoadStore));

    // --- Copy to host data to device memory
    gpuErrchk(cudaMemcpyToArray(cuArray, 0, 0, thrust::raw_pointer_cast(h_data.data()), width*height*sizeof(float), cudaMemcpyHostToDevice));

    gpuErrchk(cudaBindSurfaceToArray(surf2D, cuArray));

    cudaArrayPrintoutSurface<<<dimGrid, dimBlock>>>(width, height);
    gpuErrchk(cudaPeekAtLastError());
    gpuErrchk(cudaDeviceSynchronize());

    gpuErrchk(cudaFreeArray(cuArray));
}
#包括
#包括
//---二维浮动纹理
纹理texRef;
//---二维表面存储器
表面粗糙度2D;
/********************/
/*CUDA错误检查*/
/********************/
#定义gpuerchk(ans){gpuAssert((ans),_文件_,_行__)}
内联void gpuAssert(cudaError\u t代码,char*文件,int行,bool abort=true)
{
如果(代码!=cudaSuccess)
{
fprintf(标准,“GPUassert:%s%s%d\n”,cudaGetErrorString(代码)、文件、行);
如果(中止)退出(代码);
}
}
/*************************************/
/*cudaArray打印输出纹理内核*/
/*************************************/
__全局\uuuuvoid cudaArrayPrintoutTexture(整数宽度、整数高度)
{
无符号整数x=blockIdx.x*blockDim.x+threadIdx.x;
无符号整数y=blockIdx.y*blockDim.y+threadIdx.y;
printf(“线程索引:(%i,%i);cudaArray=%f\n”,x,y,tex2D(texRef,x/(浮动)宽度+0.5f,y/(浮动)高度+0.5f));
}
/*************************************/
/*cudaArray打印输出纹理内核*/
/*************************************/
__全局_uuu无效cudaArrayPrintoutSurface(整数宽度、整数高度)
{
无符号整数x=blockIdx.x*blockDim.x+threadIdx.x;
无符号整数y=blockIdx.y*blockDim.y+threadIdx.y;
浮子温度;
surf2Dread(温度和温度,surf2D,x*4,y);
printf(“线程索引:(%i,%i);cudaArray=%f\n”,x,y,temp);
}
/********/
/*主要*/
/********/
void main()
{
内部宽度=3,高度=3;
推力:主矢量h_数据(宽度*高度,3.f);