我正在尝试计算代码。我被告知可以应用cudaEvent ****()。与此同时,我的原始代码使用clock_gettime()来计时。我打印由cudaEvent ****()和clock_gettime()测量的结果,如下所示。这就是我真正感到困惑的事情。
由cudaEvent测量****()
由clock_gettime()
测量注意:
Q1:由cudaEvent ****()(0.0072ms)测量的“建立上下文”花费的时间与clock_gettime()(~20.5s)测量的时间大不相同。实际上,这部分只有一行建立了一个上下文。 cudaFree(0) 这种巨大差异是如何发生的?
Q2:由cudaEvent ****()(~17.221s)测量的“时间步进”花费的时间是clock_gettime()(~8.43s)测得的时间的两倍。有人告诉我,异步可能是一个可能的原因,但我并没有真正得到它。任何人都可以帮助我度过难关吗?
问题3:花费的挂钟时间非常接近clock_gettime()测量的时间。但是,我被告知cudaEvent ****()在计算cuda代码时更可取。我不知道应该涂哪一个。
===============================更新=============== ==================== 以下是我的代码的一部分,其中定义了一些定时函数和宏。
#define TIMING 1
#if TIMING
double get_time()
{
struct timespec time;
clock_gettime(CLOCK_REALTIME, &time);
return (double)time.tv_sec + (double)time.tv_nsec * 1.0e-9 ;
}
#endif
#define CUDATIMING 0
#if CUDATIMING
#define cuda_timing_init \
cudaEvent_t startEvent, stopEvent;\
float timeEvent;\
cudaEventCreate(&startEvent);\
cudaEventCreate(&stopEvent);
#define cuda_timing_begin \
cudaEventRecord(startEvent, 0);
#define cuda_timing_stop(str) \
cudaEventRecord(stopEvent, 0);\
cudaEventSynchronize(stopEvent);\
cudaEventElapsedTime(&timeEvent, startEvent, stopEvent);\
printf("time spent of %s: %fms\n", str, timeEvent);
#define cuda_timing_destroy \
cudaEventDestroy(startEvent);\
cudaEventDestroy(stopEvent);
#endif
我使用这些函数和宏来计时。
===========================更新20150823 ================== =============
这是我的代码的基本结构,包括时间。我不确定它是否有助于解决我的时间问题。
void
copy_float_from_host_to_dev(float *h_p, float **d_pp, int size)
{
if_error(cudaMalloc(d_pp, size));
if_error(cudaMemcpy(*d_pp, h_p, size, cudaMemcpyHostToDevice));
}
void
copy_int_from_host_to_dev(int *h_p, int **d_pp, int size)
{
if_error(cudaMalloc(d_pp, size));
if_error(cudaMemcpy(*d_pp, h_p, size, cudaMemcpyHostToDevice));
}
int
main(int argc, char **argv)
{
// init
// totally CPU codes
// ......
#if TIMING
double t1, t2, t3, t4, t5, t6;
t1 = get_time();
#endif
#if CUDATIMING
cuda_timing_init;
cuda_timing_begin;
#endif
// init data structure
// totally CPU codes
// ......
#if TIMING
t2 = get_time();
#endif
#if CUDATIMING
cuda_timing_stop("init data structure");
cuda_timing_begin;
#endif
// establish context
cudaFree((void*)0);
#if TIMING
t3 = get_time();
#endif
#if CUDATIMING
cuda_timing_stop("establish context");
cuda_timing_begin;
#endif
// rearrange data
// totally CPU codes
// data on CPU side has different structure
// compared to data on GPU side, so I need
// to rearrange it.
// ......
#if TIMING
t4 = get_time();
#endif
#if CUDATIMING
cuda_timing_stop("rearrange data");
cuda_timing_begin;
#endif
// copy data from host to device
// about 10 copies. the following are 2 of them
// all use copy_float/int_from_host_to_dev
// h_lap --> d_lap
copy_float_from_host_to_dev(h_lap, &d_lap, lapsize);
// h_etol --> d_etol
copy_int_from_host_to_dev(h_etol, &d_etol, etolsize);
// ......
#if TIMING
t5 = get_time();
#endif
#if CUDATIMING
cuda_timing_stop("copy data");
cuda_timing_begin;
#endif
// time stepping
for(step = 1; step < para->nstep; step++)
{
/* kernel_1: matrix-vector multiplication.
* The matrix is special, so multiplication
* can be very fast.
* atomic operations are involved
* no data transfers between host and device */
kernel_1<<<32768, 128>>>(......);
/* kernel_2: vector operations.
* Assuming that a,b,c,d are vectors,
* what kernel_2 does is: a=2*a-b+c*d
* no data transfers between host and device */
kernel_2<<<16384, 128>>>(......);
}
#if TIMING
t6 = get_time();
printf("total time: %fs\n", t6-t1);
printf(" init data structure: %fs\n", t2-t1);
printf(" establish context: %fs\n", t3-t2);
printf(" rearrange data: %fs\n", t4-t3);
printf(" copy data: %fs\n", t5-t4);
printf(" time stepping: %fs\n", t6-t5);
#endif
#if CUDATIMING
cuda_timing_stop("time stepping");
cuda_timing_destroy;
#endif
// destroy data structure
// totally CPU codes
// ......
return 0;
}
答案 0 :(得分:1)
您只提供了一个代码示例,因此我只能提供一个答案:
由cudaEvent ****()(0.0072ms)测量的“建立上下文”花费的时间与clock_gettime()(~20.5s)测量的时间大不相同。实际上,这部分只有一行建立了一个上下文。 cudaFree(0)这种巨大的差异是如何发生的?
您假设cudaFree
调用建立了CUDA上下文是不正确的。惰性上下文建立发生在需要直接与上下文交互的第一个调用。在这种情况下,您的事件计时代码正在建立上下文,因此cudaFree
调用基本上是免费的。这就是为什么两种计时方法之间存在大的挂钟时间差异的原因。