关于CUDA中恒定内存数据的问题

关于CUDA中恒定内存数据的问题,cuda,gpgpu,nvidia,Cuda,Gpgpu,Nvidia,我有一个CUDA应用程序,我试图使用恒定内存。但是当我在主函数所在的同一个文件中编写内核时,只有常量内存中的数据才能在内核中被识别。否则,如果我在其他文件中声明内核函数,那么常量内存将变为0,并且操作正常。我提供了一个简单的虚拟代码,可以更容易地解释这个问题。这个程序有一个48x48矩阵,分为16x16个块,我在其中存储随机数1到50。在内核中,我将存储在常量内存中的数字添加到块中的每一行。代码如下: 头文件: #include <windows.h> #include <do

我有一个CUDA应用程序,我试图使用恒定内存。但是当我在主函数所在的同一个文件中编写内核时,只有常量内存中的数据才能在内核中被识别。否则,如果我在其他文件中声明内核函数,那么常量内存将变为0,并且操作正常。我提供了一个简单的虚拟代码,可以更容易地解释这个问题。这个程序有一个48x48矩阵,分为16x16个块,我在其中存储随机数1到50。在内核中,我将存储在常量内存中的数字添加到块中的每一行。代码如下:

头文件:

#include <windows.h>
#include <dos.h>
#include <stdio.h>
#include <conio.h>
#include <math.h>

#include <cuda.h>
#include <cuda_runtime.h>
#include <cutil.h>
#include <curand.h>
#include <curand_kernel.h>

__constant__ int test_cons[16];

__global__ void test_kernel_1(int *,int *);
int main(int argc,char *argv[])
{   int *mat,*dev_mat,*res,*dev_res;
    int i,j;
    int test[16 ]   = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
    cudaMemcpyToSymbol(test_cons,test,16*sizeof(int));
    mat = (int *)malloc(48*48*sizeof(int));
    res = (int *)malloc(48*48*sizeof(int));
    memset(res,0,48*48*sizeof(int));

    srand(time(NULL));
    for(i=0;i<48;i++)
    {   for(j=0;j<48;j++)
        {   mat[i*48+j] = rand()%(50-1)+1;
            printf("%d\t",mat[i*48+j] );
        }
        printf("\n");
    }

    cudaMalloc((void **)&dev_mat,48*48*sizeof(int));
    cudaMemcpy(dev_mat,mat,48*48*sizeof(int),cudaMemcpyHostToDevice);
    cudaMalloc((void **)&dev_res,48*48*sizeof(int));

    dim3 gridDim(48/16,48/16,1);
    dim3 blockDim(16,16,1);

    test_kernel_1<<< gridDim,blockDim>>>(dev_mat,dev_res);

    cudaMemcpy(res,dev_res,48*48*sizeof(int),cudaMemcpyDeviceToHost);

    printf("\n\n\n\n");
    for(i=0;i<48;i++)
    {   for(j=0;j<48;j++)
        {   printf("%d\t",res[i*48+j] );
        }
        printf("\n");
    }

    cudaFree(dev_mat);
    cudaFree(dev_res);
    free(mat);
    free(res);
    exit(0);
}
__global__ void test_kernel_1(int *dev_mat,int* dev_res)
{
    int row = blockIdx.y*blockDim.y+threadIdx.y;
    int col = blockIdx.x*blockDim.x +threadIdx.x;

    dev_res[row*48+col] = dev_mat[row*48+col] + test_cons[threadIdx.x];
}
现在,当我在主程序文件和主程序中声明内核函数时,常量内存值是正确的,否则如果它在不同的文件中,
test\u cons[threadIdx.x]
值将变为0


我遇到过这样的问题,讨论同样的问题,但我没有正确地理解它。如果有人能告诉我为什么会发生这种情况,以及我需要做什么来避免这个问题,那将非常有帮助。任何形式的帮助都将不胜感激。谢谢。

我最近刚刚回答了一个类似的问题

CUDA可以处理引用其他文件中的设备代码(入口点)或符号的代码,但它需要使用设备链接进行单独编译(如我上面给出的链接中所述)。(单独编译/链接需要CC 2.0或更高版本)

因此,如果修改链接步骤,可以在给定文件中使用
\uuuu常量\uuuu
变量,并从其他文件中引用它

如果没有(如果没有指定单独的编译和设备链接),那么引用
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
变量的设备代码、引用
\uuuuuuuuuuuuuuuuuuuuuuuuu

因此:

__constant__ int test_cons[16];
这:

这是:

dev_res[row*48+col] = dev_mat[row*48+col] + test_cons[threadIdx.x];

所有文件都必须在同一个文件中。

我最近刚刚回答了一个类似的问题

CUDA可以处理引用其他文件中的设备代码(入口点)或符号的代码,但它需要使用设备链接进行单独编译(如我上面给出的链接中所述)。(单独编译/链接需要CC 2.0或更高版本)

因此,如果修改链接步骤,可以在给定文件中使用
\uuuu常量\uuuu
变量,并从其他文件中引用它

如果没有(如果没有指定单独的编译和设备链接),那么引用
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
变量的设备代码、引用
\uuuuuuuuuuuuuuuuuuuuuuuuu

因此:

__constant__ int test_cons[16];
这:

这是:

dev_res[row*48+col] = dev_mat[row*48+col] + test_cons[threadIdx.x];

所有这些都需要在同一个文件中。

以上答案完全可以接受,我添加了这个,因为用户无法使其工作。你可以接受以上答案,这只是供你参考

Kernel.cu文件:

#include <stdio.h>

__constant__ int test_cons[16];

void copymemory (int *test)
{
      cudaMemcpyToSymbol(test_cons,test,16*sizeof(int));
}

__global__ void test_kernel_1(int *dev_mat,int* dev_res)
{
    int row = blockIdx.y*blockDim.y+threadIdx.y;
    int col = blockIdx.x*blockDim.x +threadIdx.x;

    if (threadIdx.x ==0)
    {
        printf ("testcons[0] is %d\n", test_cons[threadIdx.x]) ;
    }
    dev_res[row*48+col] = dev_mat[row*48+col] + test_cons[threadIdx.x];
 }
#包括
__常数检验[16];
无效复制内存(int*测试)
{
cudaMemcpyToSymbol(测试,16*sizeof(int));
}
__全局无效测试内核1(int*dev\u mat,int*dev\u res)
{
int row=blockIdx.y*blockDim.y+threadIdx.y;
int col=blockIdx.x*blockDim.x+threadIdx.x;
if(threadIdx.x==0)
{
printf(“testcons[0]是%d\n”,test_cons[threadIdx.x]);
}
dev_res[row*48+col]=dev_mat[row*48+col]+测试约束[threadIdx.x];
}
simple.cu文件

#include <stdio.h>
#include <math.h>

#include <cuda.h>
#include <cuda_runtime.h>
#include <curand.h>
#include <curand_kernel.h>


void copymemory (int *temp) ;

__global__ void test_kernel_1(int *,int *);

int main(int argc,char *argv[])
{
    int *mat,*dev_mat,*res,*dev_res;
    int i,j;
    int test[16 ]   = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
    mat = (int *)malloc(48*48*sizeof(int));
    res = (int *)malloc(48*48*sizeof(int));
    memset(res,0,48*48*sizeof(int));


    copymemory (test) ;
    srand(time(NULL));
    for(i=0;i<48;i++)
    {
            for(j=0;j<48;j++)
            {
                mat[i*48+j] = rand()%(50-1)+1;
                //printf("%d\t",mat[i*48+j] );
            }
            //printf("\n");
    }

    cudaMalloc((void **)&dev_mat,48*48*sizeof(int));
    cudaMemcpy(dev_mat,mat,48*48*sizeof(int),cudaMemcpyHostToDevice);
    cudaMalloc((void **)&dev_res,48*48*sizeof(int));
    dim3 gridDim(48/16,48/16,1);
    dim3 blockDim(16,16,1);

    test_kernel_1<<< gridDim,blockDim>>>(dev_mat,dev_res);
    cudaMemcpy(res,dev_res,48*48*sizeof(int),cudaMemcpyDeviceToHost);
    for(i=0;i<48;i++)
    {
           for(j=0;j<48;j++)
            {
                    //   printf("%d\t",res[i*48+j] );
            }
            //printf("\n");
    }

    cudaFree(dev_mat);
    cudaFree(dev_res);
    free(mat);
    free(res);
    exit(0);
}
#包括
#包括
#包括
#包括
#包括
#包括
无效复制内存(int*temp);
__全局无效测试内核1(int*,int*);
int main(int argc,char*argv[])
{
int*mat、*dev_mat、*res、*dev_res;
int i,j;
int test[16]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
mat=(int*)malloc(48*48*sizeof(int));
res=(int*)malloc(48*48*sizeof(int));
memset(res,0,48*48*sizeof(int));
复制存储器(测试);
srand(时间(空));

对于(i=0;i以上答案完全可以接受,我添加此选项是因为用户无法使其正常工作。您可以接受以上答案,此选项仅供参考

Kernel.cu文件:

#include <stdio.h>

__constant__ int test_cons[16];

void copymemory (int *test)
{
      cudaMemcpyToSymbol(test_cons,test,16*sizeof(int));
}

__global__ void test_kernel_1(int *dev_mat,int* dev_res)
{
    int row = blockIdx.y*blockDim.y+threadIdx.y;
    int col = blockIdx.x*blockDim.x +threadIdx.x;

    if (threadIdx.x ==0)
    {
        printf ("testcons[0] is %d\n", test_cons[threadIdx.x]) ;
    }
    dev_res[row*48+col] = dev_mat[row*48+col] + test_cons[threadIdx.x];
 }
#包括
__常数检验[16];
无效复制内存(int*测试)
{
cudaMemcpyToSymbol(测试,16*sizeof(int));
}
__全局无效测试内核1(int*dev\u mat,int*dev\u res)
{
int row=blockIdx.y*blockDim.y+threadIdx.y;
int col=blockIdx.x*blockDim.x+threadIdx.x;
if(threadIdx.x==0)
{
printf(“testcons[0]是%d\n”,test_cons[threadIdx.x]);
}
dev_res[row*48+col]=dev_mat[row*48+col]+测试约束[threadIdx.x];
}
simple.cu文件

#include <stdio.h>
#include <math.h>

#include <cuda.h>
#include <cuda_runtime.h>
#include <curand.h>
#include <curand_kernel.h>


void copymemory (int *temp) ;

__global__ void test_kernel_1(int *,int *);

int main(int argc,char *argv[])
{
    int *mat,*dev_mat,*res,*dev_res;
    int i,j;
    int test[16 ]   = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
    mat = (int *)malloc(48*48*sizeof(int));
    res = (int *)malloc(48*48*sizeof(int));
    memset(res,0,48*48*sizeof(int));


    copymemory (test) ;
    srand(time(NULL));
    for(i=0;i<48;i++)
    {
            for(j=0;j<48;j++)
            {
                mat[i*48+j] = rand()%(50-1)+1;
                //printf("%d\t",mat[i*48+j] );
            }
            //printf("\n");
    }

    cudaMalloc((void **)&dev_mat,48*48*sizeof(int));
    cudaMemcpy(dev_mat,mat,48*48*sizeof(int),cudaMemcpyHostToDevice);
    cudaMalloc((void **)&dev_res,48*48*sizeof(int));
    dim3 gridDim(48/16,48/16,1);
    dim3 blockDim(16,16,1);

    test_kernel_1<<< gridDim,blockDim>>>(dev_mat,dev_res);
    cudaMemcpy(res,dev_res,48*48*sizeof(int),cudaMemcpyDeviceToHost);
    for(i=0;i<48;i++)
    {
           for(j=0;j<48;j++)
            {
                    //   printf("%d\t",res[i*48+j] );
            }
            //printf("\n");
    }

    cudaFree(dev_mat);
    cudaFree(dev_res);
    free(mat);
    free(res);
    exit(0);
}
#包括
#包括
#包括
#包括
#包括
#包括
无效复制内存(int*temp);
__全局无效测试内核1(int*,int*);
int main(int argc,char*argv[])
{
int*mat、*dev_mat、*res、*dev_res;
int i,j;
int test[16]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
mat=(int*)malloc(48*48*sizeof(int));
res=(int*)malloc(48*48*sizeof(int));
memset(res,0,48*48*sizeof(int));
复制存储器(测试);
srand(时间(空));

对于(i=0;i您已经用您提供的链接回答了您自己的问题。该链接确切地说明了如何解决您的问题。您必须在主文件中声明一个包装器,并从您拥有内核的文件调用该包装器,以便将值复制到常量内存中。是的,我知道该链接实际上回答了我的问题,但它如果您能在我提供的程序中编写必要的代码,然后将其作为答案发布,那将非常有帮助。我无法完全理解该链接。谢谢。我做了此链接中提到的一些事情,但它仍然不起作用。我不完全理解