请问下cuda调试查看变量值的问题

下面这段代码:
global static void sumofSquares(int* num, int* result, clock_t gpu_time){

int sum = 0;
clock_t start = clock()	;

for(int i = 0 ;i < DATA_SIZE; i++){

	sum += num[i]*num[i];
}

*result = sum;
gpu_time = clock()-start;

}
启用cuda调试时可以查看sum ,num的值,但是无法查看start的值,跳出 kernel函数后 又可以查看 clock_t 变量的值了,请问是怎么回事?

楼主您好,您描述的现象不可能存在。

我刚才重试了您的代码,
可以正确的观察看start的值的。

我在编译您的代码的时候,将您的代码按照yixi的意见修改为了:
clock_t * gpu_time;
将clock()改成了clock()分号

这样是可以观察到的。
(您原来那样这个值不会返回,等于无输出的,start和gpu_time均被干掉的)

LZ你好,你说的问题具体什么原因我不清楚,但是,从你的程序上看,clock_t gpu_time这个参数,是不是应该改成clock_t *gpu_time?

是的。楼主可能是故意写错的。让我们来娱乐的。

感谢yixi和我的讨论(该讨论构成了2#,3#,4#)。

感谢各位,改成clock_t *gpu_time后可以查看 start的值了,即使是clock() ;也是可以的。但是 我不明白,函数里面声明的变量start和 函数参数根本没有关系,为什么会查看不了start的值呢

另外kernel函数的参数必须都是指针形式吗 ,为什么

请查看3#最后括号里面的内容。

LZ您好:

1:这个不一定的,可以是指针,也可以不是。
2:因为kernel是void类型的,没有返回值,只能通过指针将内部计算的结果输出到global memory里面。因此如果一个参数你打算kernel自用的话,可以是非指针类型,如果要保存kernel的计算结果,必须用指针。(以及,这里不考虑__device__的全局变量情况)
3:如果某个计算结果没有通过指针将结果输出,编译的时候会将相关部分拿掉,正如3#所说。因为一个函数作为一个黑盒,这种部分并无影响输出,所以无法从外界推断其内部是否真的存在这一段,既如此,干脆干掉。

大致这样,供您参考。

祝您编码顺利~

感谢各位的讲解,受益良多,尤其是ice的话让我明白了横少千军的意思,victory:

欢迎LZ常来论坛哈~~

又出现了一个新的问题:

#include <stdio.h>

#include <stdlib.h>

#include “cuda_runtime.h”

#include <time.h>

#include “device_launch_parameters.h”

#define DATA_SIZE 1048567

#define THREAD_NUM 256

int data[DATA_SIZE];

bool InitCUDA(){

int	count;

cudaGetDeviceCount(&count) ;

if ( count == 0)
{
	fprintf(stderr, "There is no device.\n") ;

	return false;
}

int	 i;

for ( i = 0 ;i < count ; i++)
{
	cudaDeviceProp prop ;

	if ( cudaGetDeviceProperties(& prop ,i) == cudaSuccess)
	{
		if ( prop.major >= 1)
		{
			break;
		}
	}
}
	if ( i == count)
	{
		fprintf(stderr ,"There is no device supporting CUDA1.x.\n");

		return false;
	}

	cudaSetDevice( i );

	return true;

}

void generateNumbers(int* data, int size){

for (int i = 0; i < size; i++)
{
	data[i] = rand()%10;
}

}

global static void sumofSquares(int* num, int* result, clock_t* gpu_time){

int sum = 0;

// const int tid = threadIdx.x;
//
// const int size = DATA_SIZE/THREAD_NUM;

clock_t start = clock();

for(int i = 0 ;i < DATA_SIZE; i++){

	sum += num[i]*num[i];
}

*result = sum;

*gpu_time = clock()-start;

}
int main(){

if (! InitCUDA())
{
	return 0;
}

printf("Hello word ,cuda has been initialized.\n");

generateNumbers(data,DATA_SIZE);

int* gpudata,*gpu_result;

clock_t* gpu_time = NULL;

clock_t gpu_time_used;

clock_t cpu_time;

clock_t cpu_time_used;

cudaMalloc((void**)&gpudata, sizeof(int)*DATA_SIZE);

cudaMalloc((void**)&gpu_result, sizeof(int));

cudaMalloc((void**)gpu_time, sizeof(clock_t));

cudaMemcpy(gpudata, data,sizeof(int)*DATA_SIZE,cudaMemcpyHostToDevice);

sumofSquares<<<1, 1, 0>>>(gpudata,gpu_result, gpu_time);

cudaMemcpy(&gpu_time_used, gpu_time, sizeof(clock_t),cudaMemcpyDeviceToHost);

int sum ;

cudaMemcpy(&sum	,gpu_result,sizeof(int),cudaMemcpyDeviceToHost);

printf("sum(gpu)=%d,gpu_time_used=%d\n", sum, gpu_time_used	);

// sum = 0;
// clock_t cpu_start = clock();

// for (int i = 0 ;i < DATA_SIZE; i++)
// {
// sum += data[i]*data[i];
//
// }
// cpu_time_used = clock() - cpu_start;
//
// printf(“sum(cpu)=%d,cpu_time_used=%d\n”,sum, cpu_time_used);
return 0;
}

上面代码中,cudaMalloc((void**)gpu_time, sizeof(clock_t)); gpu_time 缺了个取地址符,导致结果:sum(cpu) 和 cpu_time_used均不正确。
后修正为&gpu_time 后,sum(cpu)和cpu_time_used 均运算正确。
想问的问题是:sumofSquares<<<1, 1, 0>>>(gpudata,gpu_result, gpu_time); gpu_time 和gpu_result 不存在任何关系,为什么会影响结果正确性?

不好意思 ,上面把 sum(gpu) 和 gpu_time_used写成了 cpu的了,代码中是正确的,下面文字说明的部分写错了,应将 sum(cpu) 和 cpu_time_used 更正为 sum(gpu) 和 gpu_time_used。
问题有两个问题: gpu_time 的编码正确与否 是怎样影响 gpu_result 的值的?

将cudamalloc 中 将 gpu_time 改 成正确后,但kernel 中计算出的 gpu_time 值 为何与最后打印输出的值 不一样?

[attach]3202[/attach]

调试kernel函数得到的gpu_time

[attach]3203[/attach]

打印输出结果

LZ您好,我看晕了,您13#也没说清楚(指代不清),眼睛疼痛中,需要休息24h,明天见。

楼主:
上面代码中,cudaMalloc((void**)gpu_time, sizeof(clock_t)); gpu_time 缺了个取地址符,导致结果:sum(cpu) 和 cpu_time_used均不正确。
后修正为&gpu_time 后,sum(cpu)和cpu_time_used 均运算正确。
想问的问题是:sumofSquares<<<1, 1, 0>>>(gpudata,gpu_result, gpu_time); gpu_time 和gpu_result 不存在任何关系,为什么会影响结果正确性?

回复:
因为如果您使用cudaMalloc(gpu_time, sizeof(clock_t));
而不是&gpu_time, 则cudaMalloc无法将分配的的缓冲区首地址写入gpu_time,
而因为gpu_time将不在含有一个有效的地址,而使用该地址的kernel将出错。

明白了吗?

或者简单的说,

虽然您的kernel需要多个参数,但只要有一个参数是错误的,那么整体就可能出错。
而不是您想想的那样,使用了参数gpu_result和gpu_time, 当gpu_time是错误的时候,可以得到部分的正确结果(gpu_result), 那样是不行的。

程序的编写是需要严格的逻辑上的正确的,您不能抱怨您写错了一点,而部分其他计算成功。

cudamalloc 中将 gpu_time 改成 &gpu_time , 但是最后打印输出的 gpu_time _used与 kernel中计算出的不一样是怎么回事

楼主您好,

您的printf的gpu_time_used实际上打印了指针本身,而不是他指向的值。
只有*gpu_time_used才能提领出它指向的值。

请考虑在printf中使用*gpu_time_used而不是gpu_time_used。
谢谢!

但是 gpu_time_used 是 clock_t类型 ,不是指针啊

额。看错了。。我将您的gpu_time_used和gpu_time这2个变量看混了(因为他们名字相像)。。。

那么楼主的代码无问题,唯一可能存在问题的地方在于:
printf(“%d”, gpu_time_used);
clock_t类型不一定是32-bit的,如果您的时间范围在32_bit内可以表达,建议改成:
printf(“%d”, (int)gpu_time_used);
当然这个可能无影响。。。但建议改成这个试验下。

因为从您的描述看:
您的kernel成功以<<<1,1>>>执行到最后了(您从nsight里面观察到了*gpu_time的值),
以及执行完毕后就一个cudaMemcpy后来此值,写的也没问题。

所以最大可能就是后面的printf了,建议修改下。。

昨晚12点看混2个变量,深表歉意。
请尝试一下这个。

感谢来访。