Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
CUDA纹理的不同寻址方式_Cuda_Textures_Border_Addressing Mode - Fatal编程技术网

CUDA纹理的不同寻址方式

CUDA纹理的不同寻址方式,cuda,textures,border,addressing-mode,Cuda,Textures,Border,Addressing Mode,我正在边框寻址模式下使用CUDA纹理(cudaAddressModeBorder)。我正在使用tex2D()读取纹理坐标。当纹理坐标位于纹理之外时,tex2D()返回0 如何将返回的边界值从0更改为其他值?我可以手动检查纹理坐标并自己设置边界值。我想知道是否有CUDA API可以设置这样的边界值。到目前为止(CUDA 5.5),CUDA纹理获取行为是不可自定义的。4种自动内置模式(即边框、夹紧、包裹和镜像)中只有1种可用于超出范围的纹理提取。正如sgarizvi所述,CUDA只支持四种不可定制的

我正在边框寻址模式下使用CUDA纹理(
cudaAddressModeBorder
)。我正在使用
tex2D()
读取纹理坐标。当纹理坐标位于纹理之外时,
tex2D()
返回
0


如何将返回的边界值从
0
更改为其他值?我可以手动检查纹理坐标并自己设置边界值。我想知道是否有CUDA API可以设置这样的边界值。

到目前为止(CUDA 5.5),CUDA纹理获取行为是不可自定义的。4种自动内置模式(即边框夹紧包裹镜像)中只有1种可用于超出范围的纹理提取。

正如sgarizvi所述,CUDA只支持四种不可定制的地址模式,即夹紧边框包裹镜像,如第3.2.11.1节所述。CUDA编程指南的一部分

前两种方法在非标准化坐标和标准化坐标下都有效,而后两种方法仅在标准化坐标下有效

描述前两个,为了简单起见,让我们考虑非标准坐标情况和考虑1D信号。在这种情况下,输入序列是

c[k]
,其中
k=0,…,M-1

cudaAddressModeClamp

信号
c[k]
k=0,…,M-1
之外继续,因此
c[k]=c[0]
对于
k<0
,而
c[k]=c[M-1]
对于
k>=M

cudaAddressModeBorder

信号
c[k]
k=0,…,M-1
之外继续,因此
c[k]=0
对于
k<0
k>=M

现在,为了描述最后两种地址模式,我们不得不考虑归一化坐标,使得1D输入信号样本被假定为<代码> C[K/M] < /代码>,<代码> k=0,…,M-1 < /代码> .< cudaAddressModeWrap

信号
c[k/M]
k=0,…,M-1
之外继续,因此它是周期性的,周期等于
M
。换句话说,
c[(k+p*M)/M]=c[k/M]
用于任何(正、负或消失)整数
p

cudaAddressModeMirror

信号
c[k/M]
k=0,…,M-1
之外继续,因此它是周期性的,周期等于
2*M-2
。换句话说,
c[l/M]=c[k/M]
对于任何
l
k
,使得
(l+k)mod(2*M-2)=0

以下代码说明了所有四种可用的地址模式

#include <stdio.h>

texture<float, 1, cudaReadModeElementType> texture_clamp;
texture<float, 1, cudaReadModeElementType> texture_border;
texture<float, 1, cudaReadModeElementType> texture_wrap;
texture<float, 1, cudaReadModeElementType> texture_mirror;

/********************/
/* 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);
    }
}

/******************************/
/* CUDA ADDRESS MODE CLAMPING */
/******************************/
__global__ void Test_texture_clamping(const int M) {

    printf("Texture clamping - i = %i; value = %f\n", -threadIdx.x, tex1D(texture_clamp, -(float)threadIdx.x));
    printf("Texture clamping - i = %i; value = %f\n", M + threadIdx.x, tex1D(texture_clamp, (float)(M + threadIdx.x)));

}

/****************************/
/* CUDA ADDRESS MODE BORDER */
/****************************/
__global__ void Test_texture_border(const int M) {

    printf("Texture border - i = %i; value = %f\n", -threadIdx.x, tex1D(texture_border, -(float)threadIdx.x));
    printf("Texture border - i = %i; value = %f\n", M + threadIdx.x, tex1D(texture_border, (float)(M + threadIdx.x)));

}

/**************************/
/* CUDA ADDRESS MODE WRAP */
/**************************/
__global__ void Test_texture_wrap(const int M) {

    printf("Texture wrap - i = %i; value = %f\n", -threadIdx.x, tex1D(texture_wrap, -(float)threadIdx.x/(float)M));
    printf("Texture wrap - i = %i; value = %f\n", M + threadIdx.x, tex1D(texture_wrap, (float)(M + threadIdx.x)/(float)M));

}

/****************************/
/* CUDA ADDRESS MODE MIRROR */
/****************************/
__global__ void Test_texture_mirror(const int M) {

    printf("Texture mirror - i = %i; value = %f\n", -threadIdx.x, tex1D(texture_mirror, -(float)threadIdx.x/(float)M));
    printf("Texture mirror - i = %i; value = %f\n", M + threadIdx.x, tex1D(texture_mirror, (float)(M + threadIdx.x)/(float)M));

}

/********/
/* MAIN */
/********/
void main(){

    const int M = 4;

    // --- Host side memory allocation and initialization
    float *h_data = (float*)malloc(M * sizeof(float));

    for (int i=0; i<M; i++) h_data[i] = (float)i;

    // --- Texture clamping
    cudaArray* d_data_clamping = NULL; gpuErrchk(cudaMallocArray(&d_data_clamping, &texture_clamp.channelDesc, M, 1)); 
    gpuErrchk(cudaMemcpyToArray(d_data_clamping, 0, 0, h_data, M * sizeof(float), cudaMemcpyHostToDevice)); 
    cudaBindTextureToArray(texture_clamp, d_data_clamping); 
    texture_clamp.normalized = false; 
    texture_clamp.addressMode[0] = cudaAddressModeClamp;

    dim3 dimBlock(2 * M, 1); dim3 dimGrid(1, 1);
    Test_texture_clamping<<<dimGrid,dimBlock>>>(M);

    printf("\n\n\n");

    // --- Texture border
    cudaArray* d_data_border = NULL; gpuErrchk(cudaMallocArray(&d_data_border, &texture_border.channelDesc, M, 1)); 
    gpuErrchk(cudaMemcpyToArray(d_data_border, 0, 0, h_data, M * sizeof(float), cudaMemcpyHostToDevice)); 
    cudaBindTextureToArray(texture_border, d_data_border); 
    texture_border.normalized = false; 
    texture_border.addressMode[0] = cudaAddressModeBorder;

    Test_texture_border<<<dimGrid,dimBlock>>>(M);

    printf("\n\n\n");

    // --- Texture wrap
    cudaArray* d_data_wrap = NULL; gpuErrchk(cudaMallocArray(&d_data_wrap, &texture_wrap.channelDesc, M, 1)); 
    gpuErrchk(cudaMemcpyToArray(d_data_wrap, 0, 0, h_data, M * sizeof(float), cudaMemcpyHostToDevice)); 
    cudaBindTextureToArray(texture_wrap, d_data_wrap); 
    texture_wrap.normalized = true; 
    texture_wrap.addressMode[0] = cudaAddressModeWrap;

    Test_texture_wrap<<<dimGrid,dimBlock>>>(M);

    printf("\n\n\n");

    // --- Texture mirror
    cudaArray* d_data_mirror = NULL; gpuErrchk(cudaMallocArray(&d_data_mirror, &texture_mirror.channelDesc, M, 1)); 
    gpuErrchk(cudaMemcpyToArray(d_data_mirror, 0, 0, h_data, M * sizeof(float), cudaMemcpyHostToDevice)); 
    cudaBindTextureToArray(texture_mirror, d_data_mirror); 
    texture_mirror.normalized = true ; 
    texture_mirror.addressMode[0] = cudaAddressModeMirror;

    Test_texture_mirror<<<dimGrid,dimBlock>>>(M);

    printf("\n\n\n");
}

硬件支持设置颜色,但未在CUDA中公开。可能是因为经典的寻址模式都不需要任何额外的参数。NVIDIA已将其注册为请求的功能。作为一种解决方法,您可以在纹理周围绘制所需颜色的1像素边框,并使用钳制寻址模式和调整的坐标。@RogerDahl我猜这只是CUDA API的问题。因为可以在DirectX中为同一硬件设置边框颜色。在任何情况下,我都无法在这种特殊情况下修改纹理,因此我没有解决方案:-)我希望这是cuda文档,而不是
cudatexturedsc::addressMode指定寻址模式。谢谢Nvidia…谢谢,非常有用。
index                  -7  -6  -5  -4  -3  -2  -1  0  1  2  3  4  5  6  7  8  9  10  11
clamp                   0   0   0   0   0   0   0  0  1  2  3  3  3  3  3  3  3   3   3
border                  0   0   0   0   0   0   0  0  1  2  3  0  0  0  0  0  0   0   0
wrap                    1   2   3   0   1   2   3  0  1  2  3  0  1  2  3  0  1   2   3
mirror                  1   2   3   3   2   1   0  0  1  2  3  3  2  1  0  0  1   2   3