cuda c编程

一段代码在windows32位系统上跑正常,但是在64位系统上跑的时候有一个cudaMemcpy报错,请问这会是什么原因?

楼主您好!

因为您只表达了“在64位平台上会出现错误,而32位不会“的说法。却没有具体代码。

所以我只能从64位平台和32位平台的常见可能出现移植性问题的角度为您出发。

最常见的问题是:您是否在64位平台下忘记考虑了指针的长度,而将它cast给一个32位的整形变量?
这样做在32位下是安全的,但在64位下会丢失高位数据。
例如:
int *p = NULL;
cudaMalloc(&p ,…);
int t = (int)p; //32位下是安全的,但64位会丢失高位数据。
int *q = (int *)t;

这可能是您从错误的原因之一。

因为您的信息量不足,目前只能分析到这里。
欢迎您继续提供代码和错误信息,以便CUDAZone China能更好的为您服务。

感谢您的来访,祝您生活愉快!

请问
int *p = NULL;
cudaMalloc(&p ,…);
int t = (int)p; //32位下是安全的,但64位会丢失高位数据。
这里的64位会丢失高位数据怎么理解,对指针的操作不是很了解,能解释详细点吗?
谢谢了!

这是出错的代码:
cudaError_t status;
size_t pitcht;
cudaMallocPitch((void**)&dev_text,&pitcht,sizeof(char)*lenofWord,k);
status=cudaMemcpy2D(dev_text,pitch_text,Text2[0],sizeof(char)*lenofWord,sizeof(char)lenofWord,k,cudaMemcpyHostToDevice);//Text2是这样一个数组Text2[k][lenofWord];
if(status!=cudaSuccess)
printf(“error1!\n”);
flag2=(int
)malloc(sizeof(int)*k);//int *flag2;
memset(flag2,0,sizeof(int)k); //初始化
int dev_f;
status=cudaMalloc((void
)&dev_f,sizeof(int)*k);
if(status!=cudaSuccess)
printf(“error2!\n”);
status=cudaMemcpy(dev_f,flag2,sizeof(int)*k,cudaMemcpyHostToDevice);
if(status!=cudaSuccess)
printf(“error3!\n”);
kernel<<<BlockOfPerGrid,ThreadOfPerBlock>>>(dev_dirc,dev_text,dev_f,pitch_dir,pitcht,k,HeightOfDictionary);//kernel函数
status=cudaMemcpy(flag2,dev_f,sizeof(int)*k,cudaMemcpyDeviceToHost);//在64位系统上这个返回不是cudaSuccess
if(status!=cudaSuccess)
printf(“error4!\n”);

楼主您好!

通过阅读您的代码,您可以得知:
(1)您在kernel<<<>>>之前的阻塞操作cudaMemcpy是可以顺利完成的。
(2)然后您启动了kernel
(3)然后您立刻继续阻塞操作cudaMemcpy, 返回了失败值。

所以您的问题必然出现在(2)或者(3)上,通过仔细观察您的(3), 此语句没有问题。
那么您的问题必然出现在您的(2)上。

因为您没有提供您的kernel的代码。所以无法得知原因。

但根据您在楼主位指出这在64位下才有问题,所以您依然可能是存在64位的移植性问题。
例如sizeof(void *)被假设成4, 或者例如sizeof(size_t)您直接在64位下没有使用8. 等等。

感谢楼主您的发帖。您成功的将自己的问题缩小了存在的范围(kernel).
欢迎您继续跟帖。
祝您假日愉快!

问上,在64位系统上,vs的项目解决方案平台是不是要换成x64,还是原来的win32就可以

楼主您好。一些类型,例如void *, 在64位的代码里中一般需要占据8个字节的。而int一般只有4个字节(对于32位和64位的编译器). 自然会放不下,导致cast的时候丢失信息了。如同将大水桶里的水,导入小水桶里,必然有一部分要流失的。:slight_smile:

感谢您的莅临。
祝您假日愉快!

您好。在64位的windows上,提供了WOW支持。提供了全套的32位的库,组件,dll等。您可以直接将configuration里的平台依然使用win32, 在当前的CPU(intel的em64t和amd的amd64下), 可以全速执行32位指令,而不会有额外开销。

所以您可以依然使用win32, 而不需x64.
:slight_smile:

嗯,这个懂了,谢谢!

但是我的代码在k不大的时候64位系统是运行正常的,k稍微大点就出错了,这个也是指针的原因吗?

我猜测有可能是越界,请检查下kernel。

我的kernel函数,但是我觉得我的kernel函数没有问题
global void kernel(char dictionary,char text,int flag,size_t pd,size_t pt,int ht,int hd)
{
int tid=threadIdx.x+blockIdx.x
blockDim.x;//一个线程为一个字典一行
if(tid<hd)
{
char dic=(char)((char
)dictionary+pd
tid);//取自典的一行
for(int i=0;i<ht;i++)//对text数据的每一行与字典匹配
{
char OneText=(char)((char*)text+pt*i);//一个词语
if(strcmp0(OneText,dic)==0)
{
flag[i]=tid;//如果找到标志在字典的位置,字典的每一行都是唯一的
}
}
}
}
求继续帮忙纠错,谢了!

请问32位系统上的代码到64位上的要怎么改,能举个例子吗,比如32位代码:
int *a=(int *)malloc(sizeof(int)10);
int dev_a;
cudaMalloc((void
)&dev_a,sizeof(int)*10);
怎么转为64位系统上的代码

我的kernel函数,但是我觉得我的kernel函数没有问题
global void kernel(char dictionary,char text,int flag,size_t pd,size_t pt,int ht,int hd)
{
int tid=threadIdx.x+blockIdx.x
blockDim.x;//一个线程为一个字典一行
if(tid<hd)
{
char dic=(char)((char
)dictionary+pd
tid);//取自典的一行
for(int i=0;i<ht;i++)//对text数据的每一行与字典匹配
{
char OneText=(char)((char*)text+pt*i);//一个词语
if(strcmp0(OneText,dic)==0)
{
flag[i]=tid;//如果找到标志在字典的位置,字典的每一行都是唯一的
}
}
}
}
求继续帮忙纠错,谢了!

请问32位系统上的代码到64位上的要怎么改,能举个例子吗,比如32位代码:
int *a=(int *)malloc(sizeof(int)10);
int dev_a;
cudaMalloc((void
)&dev_a,sizeof(int)*10);
怎么转为64位系统上的代码

flag,变量的范围是0~ht-1,是全局的数组。
每个线程都将在自己的循环里面,对同一组flag赋值,这将发生竟写现象,并且可能不符合您的算法预设。

欢迎补充,祝您编码愉快。

我的一个线程是字典的一行,字典每一行都是不一样的,所以flag会有多个线程同时读一个位置,但是不会出现同时写一个位置的情况

报的错误是:
the launch timed out and was terminated

您这段代码没有问题。如同我上文所说。可能是您kernel导致的。

您修改了系统的运行时间限制了么?