进行cudamemcpy后发现的一个问题

大概过程是这样的:我先通过linux的mmap将一个文件映射到内存中,
然后通过cudamalloc在显存申请一个相同大小的内存空间,
然后再用cudamemcpy将主机端的数据拷贝到设备端。
但是发现拷贝过去的数据好像并不完全。
以下是部分代码:

int inputfl;
   int len;
   char *base;
   struct stat fileinfo;
   char *d_data=NULL;//存储设备端分配的内存空间首地址
   cudaError_t error;//错误处理
   //打开文件
   if ((inputfl = open("/home/hitwh/wordlist.txt",O_RDONLY,0644)) == -1) {
   perror("open");
   exit(1);
   }
   //取得文件的大小
   if(fstat(inputfl,&fileinfo)==-1){
   perror("fstat:");
   close(inputfl);
   exit(1);
   }
   len=fileinfo.st_size;
   //printf("%d\n",len);
   //映射到内存
   if((base=(char *)mmap(NULL,len,PROT_READ,MAP_SHARED,inputfl,0))==MAP_FAILED){
   perror("mmap");
   close(inputfl);
   exit(1);
   }
   //在显存上申请空间
   error=cudaMalloc((void **)&d_data,len);
   if(error!=cudaSuccess){
   printf("cudamalloc returned %d->%s\n",int(error),cudaGetErrorString(error));
   printf("Result=FAIL\n");
   unmap(base,len,inputfl);
   exit(1);
   }
   //将主机内存数据拷贝到显存
   error=cudaMemcpy(d_data,base,len,cudaMemcpyHostToDevice);
   if(error!=cudaSuccess){
   printf("cudamemcpy returned %d->%s\n",int(error),cudaGetErrorString(error));
   printf("Result=FAIL\n");
   unmap(base,len,inputfl);
   release_device_memory(d_data);
   exit(1);
   }
   //启动内核函数
   memtest<<<1,1>>>(d_data,len);
   cudaDeviceSynchronize();
   release_device_memory(d_data);

通过printf(“%s”,base);可以在主机端打印出预想的值,但是在设备端打印的时候内容就不完整,可能是从中间某个部分开始打印。

楼主您抱怨的memtest()函数的代码呢?

建议发一下,否则无法知道您凭空抱怨的原因。

以及,我不建议您使用printf来肉眼判断内容是否一致,我建议您这样:

再开辟一个内存中的缓冲区,从d_data再复制回来。
然后用memcpy比较这个缓冲区和您之前的映射的那个。

这比您printf然后肉眼看靠谱。

__global__ void memtest(char * data,int data_len)
{
	int i;
	for(i=0;i<data_len;i++)
		printf("%c",data[i]);
}

还请赐教

您用printf其实有很多问题,例如device code端的编码格式、字符集,可能和您的host端printf时的环境不一致。

再例如,printf出来的需要您肉眼看,容易花眼。

再例如,设备端的printf往往有输出缓冲区大小限制(一般默认1MB左右),可能会造成困扰等。

正因为这三点,所以我才建议您复制回来,用memcpy检测的,它无这三点问题。

(实际上,memcpy也无需要用,只要您的显存没烧坏,您复制一段数据过去损坏的概率比您买中彩票还低的。)

感谢来访

版主您好:
按照您的提示我进行了测试,数据的确是正确的复制过去了,这里没有问题。
为了找到之前出现问题的原因,我进行了进一步的测试,如下:

__global__ void memtest(char * data,int data_len)
{
   int i;
   for(i=0;i<data_len;i++)
   printf("%c",data[i]);
}

我将以上代码的data_len设置为一个比较小的值(之前的值是非常大的),发现打印出来的数据是从头开始的,没有问题。
于是问题自然就定位到您说的printf缓冲区大小限制的问题,但我对此仍然有困扰,即使有大小限制,不应该是缓冲区满之后就输出吗?但实际表现出来的情况却是后面的数据将前面的覆盖,望赐教。

如果您认为CUDA的cudaMemcpy函数无问题,建议您结帖。

关于printf, 手册中没有公开的指明当缓冲区满时候的行为,因为我也无法为您具体说明,但请注意的是:
默认的1MB已经足够大,printf的输出是给您肉眼看的,1MB的数字大约是100万英文字符,正常人阅读完这些大约需要几个小时,我不认为一个正常的程序应该填充满它。
(当然您还可以通过cudaDeviceSetLimit来提升到比默认缓冲区更大的大小,但一般无意义,理由如上)

以及,如果您现在心里认为不是cudaMempcy的错了,建议您明确说明下,避免误导后来读者,您觉得如何?

感谢来访。

其实我并没有怀疑cudamemcpy有错,我的意思是在做这个事情的时候我出现了错误,不好意思,题目意思没有表达清楚。
对于printf,我这里只是为了调试才输出大量的数据(正如您所说,这种方式不好),实际程序中不会有什么输出的。
最后,谢谢版主耐心回答。