Performance Cuda profiler说我的两个内核很昂贵,但是它们的执行时间似乎很短

Performance Cuda profiler说我的两个内核很昂贵,但是它们的执行时间似乎很短,performance,cuda,kernel,profiler,Performance,Cuda,Kernel,Profiler,我使用两个内核,我们称它们为AanB 我运行CUDA探查器,它返回的结果如下: 第一个内核有44%的开销,而第二个内核有20%的开销 但是,如果我决定按照以下逻辑找出实际执行时间: timeval tim; gettimeofday(&tim, NULL); double before = tim.tv_sec+(tim.tv_usec/1000000.0); runKernel<<<...>>>(...) gettimeofday(&t

我使用两个内核,我们称它们为
A
an
B

我运行CUDA探查器,它返回的结果如下:

第一个内核有44%的开销,而第二个内核有20%的开销

但是,如果我决定按照以下逻辑找出实际执行时间:

timeval tim;
gettimeofday(&tim, NULL);
double before = tim.tv_sec+(tim.tv_usec/1000000.0);

runKernel<<<...>>>(...)

gettimeofday(&tim, NULL);
double after=tim.tv_sec+(tim.tv_usec/1000000.0);
totalTime = totalTime + after - before;
timeval-tim;
gettimeofday(&tim,NULL);
之前加倍=tim.tv\U sec+(tim.tv\U usec/1000000.0);
运行内核(…)
gettimeofday(&tim,NULL);
双后=tim.tv\u秒+(tim.tv\u usec/1000000.0);
totalTime=totalTime+之后-之前;
总时间将非常小,大约为0.0001秒


我是CUDA的新手,我不知道到底发生了什么。我应该尝试提高内核的效率,还是它们已经很有效了?

从CPU的角度来看,内核调用是异步的(请参阅)。如果内核的计时方式没有任何同步(即没有调用),那么计时就没有任何意义,因为计算仍在GPU上进行

在内核计时方面,您可以信任NVIDIA的分析器(
nvprof
/
nvvp
)。英伟达可视化分析器还可以分析程序,并提供一些关于内核可能出错的建议:分配的线程/块的无效数量等。还需要用优化标志编译代码(例如,代码> -O3)以获得相关的时序。 关于内核优化,您需要找到瓶颈(例如44%的内核),对其进行分析,并应用通常的方法:

  • 使用设备的有效带宽来计算内核的性能上限
  • 尽可能减少主机和设备之间的内存传输—即使这意味着在设备上进行效率不高的计算
  • 合并所有内存访问
  • 更喜欢共享内存访问而不是全局内存访问
  • 避免在单个扭曲内执行代码分支,因为这会序列化线程
您还可以使用指令级并行(您应该阅读)

然而,很难知道什么时候你不能再优化你的内核了。说内核的执行时间很短并不意味着什么:与什么相比,执行时间很短?你想做一些实时计算吗?可伸缩性是一个问题吗?这些是在尝试优化内核之前需要回答的一些问题


另一方面,您还应该广泛使用,并依靠
cuda memcheck
/
cuda gdb
来调试代码。

从CPU的角度来看,内核调用是异步的(请参阅)。如果内核的计时方式没有任何同步(即没有调用),那么计时就没有任何意义,因为计算仍在GPU上进行

在内核计时方面,您可以信任NVIDIA的分析器(
nvprof
/
nvvp
)。英伟达可视化分析器还可以分析程序,并提供一些关于内核可能出错的建议:分配的线程/块的无效数量等。还需要用优化标志编译代码(例如,代码> -O3)以获得相关的时序。 关于内核优化,您需要找到瓶颈(例如44%的内核),对其进行分析,并应用通常的方法:

  • 使用设备的有效带宽来计算内核的性能上限
  • 尽可能减少主机和设备之间的内存传输—即使这意味着在设备上进行效率不高的计算
  • 合并所有内存访问
  • 更喜欢共享内存访问而不是全局内存访问
  • 避免在单个扭曲内执行代码分支,因为这会序列化线程
您还可以使用指令级并行(您应该阅读)

然而,很难知道什么时候你不能再优化你的内核了。说内核的执行时间很短并不意味着什么:与什么相比,执行时间很短?你想做一些实时计算吗?可伸缩性是一个问题吗?这些是在尝试优化内核之前需要回答的一些问题


另一方面,您还应该广泛使用,并依靠
cuda memcheck
/
cuda gdb
调试您的代码。

非常感谢,我可以问您最后一件与问题无关的事情吗,如果在内核结束后,从设备到主机有一个
cudaMemcpy
和一个
cudaFree
,那么执行时间是否正确?更具体地说,在我上面描述的情况下,在内核声明之前和
cudaFree
之后使用
gettimeofday
函数会给出正确的结果吗?是同步的,所以通常CPU计时器应该返回正确的值。请注意,还有一个异步版本:。您可以查看上描述的示例。非常感谢,我可以问您最后一件与问题无关的事情,如果在内核结束后,从设备到主机有一个
cudaMemcpy
和一个
cudaFree
,那么执行时间是否正确?更具体地说,在我上面描述的情况下,在内核声明之前和
cudaFree
之后使用
gettimeofday
函数会给出正确的结果吗?是同步的,所以通常CPU计时器应该返回正确的值。请注意,还有一个异步版本:。您可以查看上描述的示例。