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

谢谢您。(cuda代码的执行跟我原来想象的不一样,又很难跟踪,每改一次都会出现新的问题)
我现在想想,可能gpu_time_used的值是对的,因为我用cuda调试时是无法看到打印后gpu_time_used值,而查看gpu_time_used是退出cuda调试,用VC自己的调试功能,这已经不是刚才的执行过程了,所以导致结果不同。

但我现在把代码改成cuda并行执行后,代码如下:(随机生成1048567个0-9的数,计算其平方和)

#include <stdio.h>

#include <stdlib.h>

#include <assert.h>
#include "cuda_runtime.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; 

	if(tid == 0)
		start = clock();

	for(int i = tid ;i < (tid+1)*size; i++){

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

	result[tid] = sum;

	clock_t end ;
	
	if( tid == 0 )
	{
		end = clock();
		*gpu_time = end-start;
	}
}
int main(){

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

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

	generateNumbers(data,DATA_SIZE);

	int* gpudata;
	int* gpu_result;

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

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

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

	clock_t* gpu_time = NULL;

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

	clock_t gpu_time_used=0;

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

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

	int sum[THREAD_NUM];

	cudaMemcpy(sum	,gpu_result,sizeof(int)*THREAD_NUM,cudaMemcpyDeviceToHost);

	
	for ( int i = 1 ;i < THREAD_NUM; i++)
	{
		sum[0]+=sum[i];

	}
	
	printf("sum(gpu)=%d, gpu_time_used=%d\n", sum[0], gpu_time_used);

	cudaFree( gpu_time);
	cudaFree(gpudata);
	cudaFree( gpu_result);
//////////////////////////////////////////////////////////////////////////
	clock_t cpu_start = clock();

	int cpu_sum = 0;
	
	for (int i = 0 ;i < DATA_SIZE; i++)
	{
		cpu_sum	+= data[i]*data[i];

	}
	clock_t cpu_time_used = clock() - cpu_start;

	printf("sum(cpu)=%d, cpu_time_used=%d\n",cpu_sum, cpu_time_used);

	return 0;
}

执行结果:
sum(gpu)=-455073962, gpu_time_used=71559570
sum(cpu)=29887568, cpu_time_used=2

难以理解:sum(gpu) 还出现了负数。但我仔细查看了代码,没有发现有不对的地方,请您帮我看下,这段代码问题出在哪里

额。。。楼主你真心调笑了。。。

你看的gpu_time_used是用的VC的local窗口看的??
我。。。。。。

那个是将gpu_time_used作为host上的指针提领后显示的值。。。。我以为你是在nsight下的watch窗口中看到的。。。
(请立刻重新使用nsight调试,并确保您是<<<1,1>>>线程形状,然后在kernel中的最后一行,使用debug->memory窗口查看值该指针指向的值。只有这样才能观察看device memory. 您那样不行的。)


关于您的第二个问题,
楼主您确定您这里不是笔误么:
for(int i = tid ;i < (tid+1)*size; i++)
{

sum += num[ i ]*num[ i ];
}
您的tid是threadIdx.x
您的0号线程将计算从0到4K的这4K个元素的平方和;
您的1号线程将计算从1到8K的这8K个元素的平方和;

您的255号元素将计算从255到1M这1048321个元素的平方和。

您不仅仅越界了(不一定报错),还完全失去了您的本意了。
(您的本意在host上取回后,进行for(…) sum[0]+=sum[i] [ i ];显然计算区域不能重叠的)

请仔细考虑下您的代码是否符合您的本意。
感谢您的来访。
[/i]

哦 刚学cuda,对cuda调试、编码还不熟。感谢版主指导。

你指的debug->memory窗口查看是 指的 debug->windows->cuda info->cuda info1 …cuda info 4等是吗,怎么有四个一样的cuda info 窗口呢

楼主您好,

我说的memory窗口就是普通的vs窗口,不过在nsight调试下,他变成了查看设备内存了。
(以及,其他窗口,例如local variables窗口,例如watch窗口,也会如此变化,
所以你也可以用watch窗口看)

我觉得在vc的调试情况下,查看 gpu_time_used 是没有问题的 ,而且查看的值和最后打印输出的值是相同的。这个是在main里 申请的一个clock_t类型变量,非指针,也没有在kernel 函数中调用,不知版主认为我这样说对不对

既然您现在调试能看到gpu_time_used了,而且值也正确了,

那么您想说什么?

我之前建议您需要从nsight调试里看,您现在也看到,那现在无问题了。

那么有什么不对的?

如果非要评论,那么我认为您现在的对变量的观察行为是正当的行为。

现在我将 kernel函数进行了改正。(意思是让256个 thread计算平方之和)

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;

if(tid == 0)
start = clock();

for(int i = tid*size ;i < (tid+1)*size; i++){

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

result[tid] = sum;

clock_t end ;

if( tid == 0 )
{
end = clock();
*gpu_time = end-start;
}
}

但是我得到的结果和cpu 计算结果不同。
sum(gpu)=29879743, gpu_time_used=15227878
sum(cpu)=29887568, cpu_time_used=3[/i][/i]不知问题出在哪里

楼主您好,通过阅读您的代码,您还有第四个BUG:

您的常数定义:
define DATA_SIZE 1048567

无法被256整除, 导致您的GPU计算少了一些。

建议的解决方案,将上文改成:
define DATA_SIZE 1048576

(备注:这个才是1M的!!!您哪个不足1M个的,导致DATA_SIZE / 256 * 256 < DATA_SIZE的,导致部分数据未参与计算)

确实是,版主太厉害了 ,一下就看出了问题,膜拜之:handshake推荐两本cuda入门的书吧

。。。。

我没有看出来,我是人工将你的数据带入,然后发现无法整除的。。。。

(话说你也可以这样的)。

推荐两本cuda 入门的书吧

您好。新的主题建议重新开贴。

但是本次依然给予回复:
建议1:《CUDA Programming Guide》
建议2:《CUDA Best Practices Guide》

可以在本论坛的资源板块下载。