了解 CUDA 分析器输出 (nvprof)
Understanding CUDA profiler output (nvprof)
我只是在查看以下输出并试图围绕这些数字思考:
==2906== Profiling result:
Time(%) Time Calls Avg Min Max Name
23.04% 10.9573s 16436 666.67us 64.996us 1.5927ms sgemm_sm35_ldg_tn_32x16x64x8x16
22.28% 10.5968s 14088 752.18us 612.13us 1.6235ms sgemm_sm_heavy_nt_ldg
18.09% 8.60573s 14088 610.86us 513.05us 1.2504ms sgemm_sm35_ldg_nn_128x8x128x16x16
16.48% 7.84050s 68092 115.15us 1.8240us 503.00us void axpy_kernel_val<float, int=0>(cublasAxpyParamsVal<float>)
...
0.25% 117.53ms 4744 24.773us 896ns 11.803ms [CUDA memcpy HtoD]
0.23% 107.32ms 37582 2.8550us 1.8880us 8.9556ms [CUDA memcpy DtoH]
...
==2906== API calls:
Time(%) Time Calls Avg Min Max Name
83.47% 41.8256s 42326 988.18us 16.923us 13.332ms cudaMemcpy
9.27% 4.64747s 326372 14.239us 10.846us 11.601ms cudaLaunch
1.49% 745.12ms 1502720 495ns 379ns 1.7092ms cudaSetupArgument
1.37% 688.09ms 4702 146.34us 879ns 615.09ms cudaFree
...
在优化内存访问方面,比较不同的实现时我真正需要查看的数字是什么?它首先看起来像 memcpy
只需要 117.53+107.32ms
(在两个方向上),但后来有这个 API 调用 cudaMemcpy
: 41.8256s
,这是更多。此外,min/avg/max 列不会在上部和下部输出块之间相加。
为什么会有差异?"true" 对我优化内存传输很重要的数字是多少?
编辑:第二个问题是:有没有办法弄清楚谁在打电话? axpy_kernel_val
(多少次)?
总时间 的差异是由于工作是异步启动到 GPU 的。如果你有一个很长的 运行ning 内核或一组内核与主机没有显式同步,然后调用 cudaMemcpy
,cudaMemcpy
调用将在内核已完成执行。 API 调用的总时间是从启动到完成的时间,因此会与执行内核重叠。如果您 运行 通过 NVIDIA Visual Profiler 输出(nvprof -o xxx ./myApp
,然后将 xxx 导入 nvvp),您可以非常清楚地看到这一点。
差异是 分钟时间 是由于启动开销。虽然 API 分析考虑了所有启动开销,但内核时序只包含其中的一小部分。正如您在此处所见,启动开销可能约为 10-20us。
一般来说,API 调用部分让您知道 CPU 在做什么,而分析结果告诉您 GPU 在做什么。在这种情况下,我认为您没有充分利用 CPU,因为可以说 cudaMemcpy
启动得太早并且浪费了 CPU 周期。然而,在实践中,通常很难或不可能从这些空闲周期中获得任何有用的东西。
我只是在查看以下输出并试图围绕这些数字思考:
==2906== Profiling result:
Time(%) Time Calls Avg Min Max Name
23.04% 10.9573s 16436 666.67us 64.996us 1.5927ms sgemm_sm35_ldg_tn_32x16x64x8x16
22.28% 10.5968s 14088 752.18us 612.13us 1.6235ms sgemm_sm_heavy_nt_ldg
18.09% 8.60573s 14088 610.86us 513.05us 1.2504ms sgemm_sm35_ldg_nn_128x8x128x16x16
16.48% 7.84050s 68092 115.15us 1.8240us 503.00us void axpy_kernel_val<float, int=0>(cublasAxpyParamsVal<float>)
...
0.25% 117.53ms 4744 24.773us 896ns 11.803ms [CUDA memcpy HtoD]
0.23% 107.32ms 37582 2.8550us 1.8880us 8.9556ms [CUDA memcpy DtoH]
...
==2906== API calls:
Time(%) Time Calls Avg Min Max Name
83.47% 41.8256s 42326 988.18us 16.923us 13.332ms cudaMemcpy
9.27% 4.64747s 326372 14.239us 10.846us 11.601ms cudaLaunch
1.49% 745.12ms 1502720 495ns 379ns 1.7092ms cudaSetupArgument
1.37% 688.09ms 4702 146.34us 879ns 615.09ms cudaFree
...
在优化内存访问方面,比较不同的实现时我真正需要查看的数字是什么?它首先看起来像 memcpy
只需要 117.53+107.32ms
(在两个方向上),但后来有这个 API 调用 cudaMemcpy
: 41.8256s
,这是更多。此外,min/avg/max 列不会在上部和下部输出块之间相加。
为什么会有差异?"true" 对我优化内存传输很重要的数字是多少?
编辑:第二个问题是:有没有办法弄清楚谁在打电话? axpy_kernel_val
(多少次)?
总时间 的差异是由于工作是异步启动到 GPU 的。如果你有一个很长的 运行ning 内核或一组内核与主机没有显式同步,然后调用 cudaMemcpy
,cudaMemcpy
调用将在内核已完成执行。 API 调用的总时间是从启动到完成的时间,因此会与执行内核重叠。如果您 运行 通过 NVIDIA Visual Profiler 输出(nvprof -o xxx ./myApp
,然后将 xxx 导入 nvvp),您可以非常清楚地看到这一点。
差异是 分钟时间 是由于启动开销。虽然 API 分析考虑了所有启动开销,但内核时序只包含其中的一小部分。正如您在此处所见,启动开销可能约为 10-20us。
一般来说,API 调用部分让您知道 CPU 在做什么,而分析结果告诉您 GPU 在做什么。在这种情况下,我认为您没有充分利用 CPU,因为可以说 cudaMemcpy
启动得太早并且浪费了 CPU 周期。然而,在实践中,通常很难或不可能从这些空闲周期中获得任何有用的东西。