Search code examples
cudatextures

CUDA - Convert texture from int to int4


I want to ask how can I convert this texture:

texture<int, 2, cudaReadModeElementType> text1;

to

texture<int4, 2, cudaReadModeElementType> text2;

So my problem is with the indexes. For example, imagine that I acceesed to the col 10 row 5 in text1 like this

int col 10;
int row 5;
int tex2d(text1, col, row);

But if I did the same, obviously I'm not accessing to the same data:

int col 10;
int row 5;
int4 tex2d(text2, col, row);

So, I tried like dividing the col / 4 and row /4, but I don't succeed either. I think that I should use DIV and MOD, but I don't know how.

Does anyone know how to access correctly using 4 channels? Thank you very much!


Solution

  • The only indexing you need to modify between the two cases is the horizontal (x) indexing. For the int4 case, the horizontal indexing can be divided by 4 (as compared to the int case) but it will retrieve 4 values. Here is a full example:

    $ cat t1918.cu
    #include <helper_cuda.h>
    #include <cstdio>
    #define HEIGHT  7680
    #ifndef USE_INT4
    #define WIDTH   7245
    typedef int it;
    #else
    #define WIDTH   1812
    typedef int4 it;
    #endif
    
    cudaArray * Array_Device;
    texture<it, 2,cudaReadModeElementType> Image;
    
    __global__ void k(int x, int y)
    {
      int w;
    #ifdef USE_INT4
      w = WIDTH*4;
    #else
      w = WIDTH;
    #endif
      for (y = 0; y < HEIGHT; y++)
       for (x = 0; x < w; x++){
        int nx=x, no=0;
    #ifdef USE_INT4
        no = x&3;   //modulo by 4
        nx >>= 2;   //division by 4
    #endif
        it val = tex2D(Image,nx,y);
        int rval = reinterpret_cast<int *>(&val)[no];
        if (rval != y*10000+x) {
          printf("mismatch at %d, %d, was: %d, should be: %d\n", x,y, rval, y*10000+x);
          return;
          }
        }
    }
    
    
    void p()
    {
            it *h = new it[WIDTH*HEIGHT];
            // this dataset and test-case only works for textures up to width of 9999 for int or 2499 for int4
            for (int i = 0; i < HEIGHT; i++)
              for (int j = 0; j < WIDTH; j++){
    #ifndef USE_INT4
                h[i*WIDTH+j] = i*10000+j;
    #else
                h[i*WIDTH+j] = {i*10000+j*4+0, i*10000+j*4+1, i*10000+j*4+2, i*10000+j*4+3};
    #endif
                }
            cudaChannelFormatDesc channelDesc = cudaCreateChannelDesc<it>();
            checkCudaErrors(cudaMallocArray(&Array_Device, &channelDesc,WIDTH,HEIGHT ));
            checkCudaErrors(cudaBindTextureToArray(Image,Array_Device));
            checkCudaErrors(cudaMemcpy2DToArray( Array_Device,
                                            0,
                                            0,
                                            h,
                                            WIDTH*sizeof(it),
                                            WIDTH*sizeof(it),
                                            HEIGHT,
                                            cudaMemcpyHostToDevice));
    
            k<<<1,1>>>(0,0);
            checkCudaErrors(cudaDeviceSynchronize());
    }
    
     int main(){
    #ifdef USE_INT4
      printf("int4\n");
    #endif
      p();
      return 0;
    }
    $ nvcc -I/usr/local/cuda/samples/common/inc -o t1918 t1918.cu
    t1918.cu(40): warning: function "tex2D(texture<T, 2, cudaReadModeElementType>, float, float) [with T=it]"
    /usr/local/cuda/bin/../targets/x86_64-linux/include/texture_fetch_functions.h(198): here was declared deprecated
    
    t1918.cu: In function ‘void p()’:
    t1918.cu:63:49: warning: ‘cudaError_t cudaBindTextureToArray(const texture<T, dim, readMode>&, cudaArray_const_t) [with T = int; int dim = 2; cudaTextureReadMode readMode = (cudaTextureReadMode)0; cudaError_t = cudaError; cudaArray_const_t = const cudaArray*]’ is deprecated [-Wdeprecated-declarations]
      checkCudaErrors(cudaBindTextureToArray(Image,Array_Device));
                                                     ^
    /usr/local/cuda/bin/../targets/x86_64-linux/include/cuda_runtime.h:1642:53: note: declared here
     static __CUDA_DEPRECATED __inline__ __host__ cudaError_t cudaBindTextureToArray(
                                                         ^~~~~~~~~~~~~~~~~~~~~~
    /usr/local/cuda/bin/../targets/x86_64-linux/include/cuda_runtime.h: In instantiation of ‘cudaError_t cudaBindTextureToArray(const texture<T, dim, readMode>&, cudaArray_const_t) [with T = int; int dim = 2; cudaTextureReadMode readMode = (cudaTextureReadMode)0; cudaError_t = cudaError; cudaArray_const_t = const cudaArray*]’:
    t1918.cu:63:49:   required from here
    /usr/local/cuda/bin/../targets/x86_64-linux/include/cuda_runtime.h:1650:55: warning: ‘cudaError_t cudaBindTextureToArray(const texture<T, dim, readMode>&, cudaArray_const_t, const cudaChannelFormatDesc&) [with T = int; int dim = 2; cudaTextureReadMode readMode = (cudaTextureReadMode)0; cudaError_t = cudaError; cudaArray_const_t = const cudaArray*]’ is deprecated [-Wdeprecated-declarations]
       return err == cudaSuccess ? cudaBindTextureToArray(tex, array, desc) : err;
                                     ~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~
    /usr/local/cuda/bin/../targets/x86_64-linux/include/cuda_runtime.h:1603:53: note: declared here
     static __CUDA_DEPRECATED __inline__ __host__ cudaError_t cudaBindTextureToArray(
                                                         ^~~~~~~~~~~~~~~~~~~~~~
    /usr/local/cuda/bin/../targets/x86_64-linux/include/cuda_runtime.h: In instantiation of ‘cudaError_t cudaBindTextureToArray(const texture<T, dim, readMode>&, cudaArray_const_t, const cudaChannelFormatDesc&) [with T = int; int dim = 2; cudaTextureReadMode readMode = (cudaTextureReadMode)0; cudaError_t = cudaError; cudaArray_const_t = const cudaArray*]’:
    /usr/local/cuda/bin/../targets/x86_64-linux/include/cuda_runtime.h:1650:55:   required from ‘cudaError_t cudaBindTextureToArray(const texture<T, dim, readMode>&, cudaArray_const_t) [with T = int; int dim = 2; cudaTextureReadMode readMode = (cudaTextureReadMode)0; cudaError_t = cudaError; cudaArray_const_t = const cudaArray*]’
    t1918.cu:63:49:   required from here
    /usr/local/cuda/bin/../targets/x86_64-linux/include/cuda_runtime.h:1609:32: warning: ‘cudaError_t cudaBindTextureToArray(const textureReference*, cudaArray_const_t, const cudaChannelFormatDesc*)’ is deprecated [-Wdeprecated-declarations]
       return ::cudaBindTextureToArray(&tex, array, &desc);
            ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~
    /usr/local/cuda/bin/../targets/x86_64-linux/include/cuda_runtime_api.h:8662:46: note: declared here
     extern __CUDA_DEPRECATED __host__ cudaError_t CUDARTAPI cudaBindTextureToArray(const struct textureReference *texref, cudaArray_const_t array, const struct cudaChannelFormatDesc *desc);
                                                  ^~~~~~~~~~~~~~~~~~~~~~
    $ cuda-memcheck ./t1918
    ========= CUDA-MEMCHECK
    ========= ERROR SUMMARY: 0 errors
    $ nvcc -I/usr/local/cuda/samples/common/inc -o t1918 t1918.cu -DUSE_INT4
    t1918.cu(40): warning: function "tex2D(texture<T, 2, cudaReadModeElementType>, float, float) [with T=it]"
    /usr/local/cuda/bin/../targets/x86_64-linux/include/texture_fetch_functions.h(198): here was declared deprecated
    
    t1918.cu: In function ‘void p()’:
    t1918.cu:63:49: warning: ‘cudaError_t cudaBindTextureToArray(const texture<T, dim, readMode>&, cudaArray_const_t) [with T = int4; int dim = 2; cudaTextureReadMode readMode = (cudaTextureReadMode)0; cudaError_t = cudaError; cudaArray_const_t = const cudaArray*]’ is deprecated [-Wdeprecated-declarations]
      checkCudaErrors(cudaBindTextureToArray(Image,Array_Device));
                                                     ^
    /usr/local/cuda/bin/../targets/x86_64-linux/include/cuda_runtime.h:1642:53: note: declared here
     static __CUDA_DEPRECATED __inline__ __host__ cudaError_t cudaBindTextureToArray(
                                                         ^~~~~~~~~~~~~~~~~~~~~~
    /usr/local/cuda/bin/../targets/x86_64-linux/include/cuda_runtime.h: In instantiation of ‘cudaError_t cudaBindTextureToArray(const texture<T, dim, readMode>&, cudaArray_const_t) [with T = int4; int dim = 2; cudaTextureReadMode readMode = (cudaTextureReadMode)0; cudaError_t = cudaError; cudaArray_const_t = const cudaArray*]’:
    t1918.cu:63:49:   required from here
    /usr/local/cuda/bin/../targets/x86_64-linux/include/cuda_runtime.h:1650:55: warning: ‘cudaError_t cudaBindTextureToArray(const texture<T, dim, readMode>&, cudaArray_const_t, const cudaChannelFormatDesc&) [with T = int4; int dim = 2; cudaTextureReadMode readMode = (cudaTextureReadMode)0; cudaError_t = cudaError; cudaArray_const_t = const cudaArray*]’ is deprecated [-Wdeprecated-declarations]
       return err == cudaSuccess ? cudaBindTextureToArray(tex, array, desc) : err;
                                     ~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~
    /usr/local/cuda/bin/../targets/x86_64-linux/include/cuda_runtime.h:1603:53: note: declared here
     static __CUDA_DEPRECATED __inline__ __host__ cudaError_t cudaBindTextureToArray(
                                                         ^~~~~~~~~~~~~~~~~~~~~~
    /usr/local/cuda/bin/../targets/x86_64-linux/include/cuda_runtime.h: In instantiation of ‘cudaError_t cudaBindTextureToArray(const texture<T, dim, readMode>&, cudaArray_const_t, const cudaChannelFormatDesc&) [with T = int4; int dim = 2; cudaTextureReadMode readMode = (cudaTextureReadMode)0; cudaError_t = cudaError; cudaArray_const_t = const cudaArray*]’:
    /usr/local/cuda/bin/../targets/x86_64-linux/include/cuda_runtime.h:1650:55:   required from ‘cudaError_t cudaBindTextureToArray(const texture<T, dim, readMode>&, cudaArray_const_t) [with T = int4; int dim = 2; cudaTextureReadMode readMode = (cudaTextureReadMode)0; cudaError_t = cudaError; cudaArray_const_t = const cudaArray*]’
    t1918.cu:63:49:   required from here
    /usr/local/cuda/bin/../targets/x86_64-linux/include/cuda_runtime.h:1609:32: warning: ‘cudaError_t cudaBindTextureToArray(const textureReference*, cudaArray_const_t, const cudaChannelFormatDesc*)’ is deprecated [-Wdeprecated-declarations]
       return ::cudaBindTextureToArray(&tex, array, &desc);
            ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~
    /usr/local/cuda/bin/../targets/x86_64-linux/include/cuda_runtime_api.h:8662:46: note: declared here
     extern __CUDA_DEPRECATED __host__ cudaError_t CUDARTAPI cudaBindTextureToArray(const struct textureReference *texref, cudaArray_const_t array, const struct cudaChannelFormatDesc *desc);
                                                  ^~~~~~~~~~~~~~~~~~~~~~
    $ cuda-memcheck ./t1918
    ========= CUDA-MEMCHECK
    int4
    ========= ERROR SUMMARY: 0 errors
    $
    

    The data stored in the texture in the int case looks like this:

       0    1    2    3    4    5    6    7 ...
    1000 1001 1002 1003 1004 1005 1006 1007...
    2000 2001 2002 2003 2004 2005 2006 2007...
    3000 3001 3002 3003 3004 3005 3006 3007...
    ...
    

    In the int4 case it looks like this:

    {   0,   1,   2,   3} {   4,   5,   6,   7} ... 
    {1000,1001,1002,1003} {1004,1005,1006,1007} ... 
    {2000,2001,2002,2003} {2004,2005,2006,2007} ...
    {3000,3001,3002,3003} {3004,3005,3006,3007} ...
    ...
    

    The kernel demonstrates how to retrieve the same value for a given (x,y) coordinate given to the kernel, in either case.

    Note that textures are deprecated and for new work you should switch to texture objects.