我有一个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_cons[threadIdx.x]
值变为0。
我遇到了这个link哪种讨论相同的问题,但我没有正确理解。如果有人能告诉我为什么会发生这种情况以及我需要做什么来避免这个问题,那将会非常有帮助。任何形式的帮助将受到高度赞赏。感谢。
答案 0 :(得分:2)
我刚刚回答了类似的问题here
CUDA可以处理引用设备代码(入口点)或其他文件中的符号的代码,但它需要使用设备链接进行单独编译(如上面链接中所描述和链接的那样)。 (并且单独的编译/链接需要CC 2.0或更高版本)
因此,如果您修改链接步骤,则可以在给定文件中包含__constant__
变量,并从其他文件引用它。
如果没有(如果你没有指定单独的编译和设备链接),那么引用__constant__
变量的设备代码,引用__constant__
变量的主机代码和定义/变量本身的声明,都需要在相同的文件中。
所以这个:
__constant__ int test_cons[16];
此:
cudaMemcpyToSymbol(test_cons,test,16*sizeof(int));
而且:
dev_res[row*48+col] = dev_mat[row*48+col] + test_cons[threadIdx.x];
所有人都需要在同一个文件中。
答案 1 :(得分:1)
上述答案完全可以接受我添加此答案,因为用户无法使其正常工作。您可以接受上述答案,仅供参考。
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];
}
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);
}
我评论了你的printf。并且内核中的printf打印值1.我还通过在main函数中更改test [0]的值进行测试,它运行良好。