解释CUDA探查器日志文件
下面是在一些代码上运行CUDA profiler(nvprof)的日志文件,这些代码混合了推力、cublas和curand。第一个是我写的内核,所以没有问题。但我不知道如何解释第2行到第5行,这占用了大量的运行时间解释CUDA探查器日志文件,cuda,profiler,thrust,nvcc,Cuda,Profiler,Thrust,Nvcc,下面是在一些代码上运行CUDA profiler(nvprof)的日志文件,这些代码混合了推力、cublas和curand。第一个是我写的内核,所以没有问题。但我不知道如何解释第2行到第5行,这占用了大量的运行时间 > Time(%) Time Calls Avg Min Max Name % s ms ms ms > > 28.12 6.82 24,543.00 0.2
> Time(%) Time Calls Avg Min Max Name % s ms ms ms
>
> 28.12 6.82 24,543.00 0.28 0.01 0.64 dev_update_dW1(doub....)
> 23.78 5.77 12,272.00 0.47 0.46 0.49 void thrust::system::cud....
> 14.32 3.47 12,272.00 0.28 0.28 0.29 void thrust::system::cud....
> 10.82 2.62 12,272.00 0.21 0.21 0.22 void thrust::system::cud....
> 4.93 1.20 24,544.00 0.05 0.05 0.05 void thrust::system::cud....
> 3.98 0.96 12,272.00 0.08 0.08 0.09 Act_dAct(double*, long, double*, double*)
第2至第5行全文如下:
第二行:无效推力::系统::cuda::细节::细节::启动\关闭\按\值>,推力::计数\迭代器,推力::空\类型,推力::空\类型,推力::空\类型,推力::空\类型,推力::空\类型,推力::空\类型>>,推力::空\类型int64,推力::元组,推力::细节::正常\迭代器,推力::系统::cuda::细节::标记,推力::使用默认值,推力::使用默认值>>,推力::系统::细节::通用::细节::最大元素减少>,推力::系统::cuda::细节::细节::阻塞线程\数组>>(双精度)
第三行:无效推力::系统::cuda::细节::细节::启动\u闭包\u按\u值>,推力::细节::正常\u迭代器>,推力::空\u类型,推力::空\u类型,推力::空\u类型,推力::空\u类型,推力::空\u类型,推力::空\u类型>>,无符号int,推力::细节::设备一元变换\u函子,推力::系统::cuda::细节::细节::阻塞线程\u数组>>(双精度)
第四行:无效推力::系统::cuda::细节::细节::按值启动关闭,双精度,推力::使用默认值>,双精度,推力::细节::正常迭代器>,推力::加号,推力::系统::cuda::细节::阻塞的线程数组>(exp\u functor)
第五行:无效推力::系统::cuda::细节::细节::按值启动\u闭包\u,无符号整数,推力::细节::设备\u生成\u函子>,推力::系统::cuda::细节::细节::阻塞的线程\u数组>>(双精度)
编辑:
我有一个函数(softmax),它使用max\u元素和transform\u reduce
void Softmax_ThrustMatrix(thrust::device_vector<double>& mat, int Nrow, int Ncol, thrust::device_vector<double>& Outmat) {
thrust::device_vector<double> x(Ncol, 0.0);
thrust::device_vector<double> v(Ncol, 0.0);
thrust::device_vector<double>::iterator mx;
double tmp = 0.0, logsm=0.0;
dim3 grid, block;
block.x = 16;
block.y = 1;
grid.x = Ncol / block.x + 1;
grid.y = 1;
for ( int i=0; i < Nrow; i++ ) {
GetRow<<<grid,block>>>(thrust::raw_pointer_cast(&mat[0]), i, Nrow, Ncol, thrust::raw_pointer_cast(&x[0]));
mx = thrust::max_element(x.begin(), x.end());
tmp = thrust::transform_reduce(x.begin(), x.end(), exp_functor(*mx), 0.0, thrust::plus<double>() );
logsm = *mx + log(tmp);
thrust::transform(x.begin(), x.end(), v.begin(), exp_functor(logsm));
SetRow<<<grid,block>>>(thrust::raw_pointer_cast(&v[0]), i, Nrow, Ncol, thrust::raw_pointer_cast(&Outmat[0]));
}
}
void Softmax\u推力矩阵(推力::装置矢量和mat、int Nrow、int Ncol、推力::装置矢量和Outmat){
推力:器件_矢量x(Ncol,0.0);
推力:装置矢量v(Ncol,0.0);
推力::设备向量::迭代器mx;
双tmp=0.0,logsm=0.0;
dim3网格,块;
块x=16;
块y=1;
grid.x=Ncol/block.x+1;
网格y=1;
对于(int i=0;i
低级别的推力代码与CUDA代码没有任何区别(至少针对GPU的推力代码)。作为一个模板库,推力在源代码级别抽象了CUDA的许多方面,但是探查器不知道推力代码和普通CUDA代码之间有什么区别
第2-5行表示4次内核启动时的探查器数据。从它们的语法可以明显看出,它们可能不是您编写的内核——它们来自于推力模板函数的深处
“启动关闭”是在引擎盖下的推力,表示由推力启动的内核执行某些功能。由于您在显示的代码中有3个推力调用,并且还显示了您编写的GetRow
和SetRow
内核,并且这些内核没有显示在您的分析器输出的任何地方,因此我不清楚您显示的分析器输出是否与您显示的代码相关。您还没有显示调用确实出现在输出中的内核的代码(dev\u update\u dW1
和Act\u dAct
),因此我很清楚,您显示的代码对于进一步解释探查器输出是没有用的
在任何情况下,第2-5行代表由推力启动的CUDA内核,这些内核来自代码中的推力调用(某处)
请注意,推力也可以为其他一些不明显的目的启动内核,例如设备向量的实例化