1

我有一些使用 PGI 编译器编译的 OpenACC 加速 C++ 代码。事情似乎很奏效,所以现在我想用分析信息来提高效率。

我通过设置生成一些时间信息:

export PGI_ACC_TIME=1

然后运行程序。

以下输出结果:

-bash-4.2$ ./a.out 
libcupti.so not found

Accelerator Kernel Timing data
    PGI_ACC_SYNCHRONOUS was set, disabling async() clauses
/home/myuser/myprogram.cpp
  _MyProgram  NVIDIA  devicenum=1
    time(us): 97,667
    75: data region reached 2 times
        75: data copyin transfers: 3
             device time(us): total=101 max=82 min=9 avg=33
    76: compute region reached 1000 times
        76: kernel launched 1000 times
            grid: [1938]  block: [128]
            elapsed time(us): total=680,216 max=1,043 min=654 avg=680
    95: compute region reached 1000 times
        95: kernel launched 1000 times
            grid: [1938]  block: [128]
            elapsed time(us): total=487,365 max=801 min=476 avg=487
    110: data region reached 2000 times
        110: data copyin transfers: 1000
             device time(us): total=6,783 max=140 min=3 avg=6
        125: data copyout transfers: 1000
             device time(us): total=7,445 max=190 min=6 avg=7

real    0m3.864s
user    0m3.499s
sys     0m0.348s

它提出了一些问题:

  1. time(us): 97,667在顶部看到。这似乎是一个总时间,但在底部,我看到了real 0m3.864s。为什么会有这样的差异?

  2. 如果time(us): 97,667是总数,为什么它比较低的值小得多,例如elapsed time(us): total=680,216

  3. 包括 ( ) 行的内核elapsed time(us): total=680,216 max=1,043 min=654 avg=680运行了 1000 次。最大值、最小值和平均值是否基于内核的每次运行值?

  4. 由于[grid][block]值可能会有所不同,经过的总值仍然是热点的良好指标吗?

  5. 对于数据区域 ( device time(us): total=6,783) 是测量传输时间还是处理数据所花费的全部时间(准备传输、接收后操作)?

  6. 行号很奇怪。例如,我的程序中的第 76 行显然是一个for循环,第 95 行是一个右大括号,第 110 行是一个变量定义。行号应该被解释为“最接近指定行号的循环”,还是以其他方式?

  7. 76 的内核包含 95 的内核。计算 76 的时间是否包括在 95 中花费的时间?如果是这样,是否有一种方便的方法可以找到在内核中花费的时间减去所有子内核的时间?

(其中一些问题有点难以理解,但我还没有找到这方面的文档,所以我想我会很彻底。)

4

1 回答 1

1

这里的部分问题是运行时找不到 CUDA 分析库 (libcupti.so),因此您只看到 PGI CPU 端分析而不是设备分析。PGI 随编译器一起提供 libcupti.so 库(在 $PGI/[linux86-64|linuxpower]/2017/cuda/[7.5|8.0]/lib64 下),但这是可选安装,因此您可能没有在系统上安装它你在跑。CUPTI 还附带 CUDA SDK,因此如果系统安装了 CUDA,您可以尝试将您设置为 LD_LIBRARY_PATH。在我的系统上,它安装在“/opt/cuda-8.0/extras/CUPTI/lib64/”中。

缺少 CUPTI 库就是为什么您会看到文件时间的糟糕时间 97,667。此外,由于您缺少 CUPTI,因此您看到的时间是从主机测量的。使用 CUPTI,除了经过的时间之外,您还可以看到每个内核的设备时间。经过时间和设备时间之间的差异是每个内核的启动开销。

最大值、最小值和平均值是否基于内核的每次运行值?

是的。

4.由于[grid]和[block]值可能不同,经过的总值是否仍然是热点的良好指标?

我倾向于首先查看平均时间,因为通常有更多机会来调整这些循环。如果您改变每次内核迭代的工作量(即网格大小发生变化),那么它可能没有那么有用,但是一个很好的起点。

现在,如果您的平均调用次数较低但调用次数较多,那么经过的时间可能主要由内核启动开销决定。在这种情况下,我会看看您是否可以组合循环或将更多工作推入每个循环。

5.对于数据区域(设备时间(us):total=6,783)是测量传输时间还是处理数据所花费的全部时间(准备传输,接收后操作)?

只是数据传输时间。对于开销,您需要使用 PGPROF/NVPROF。

6.行号很奇怪。例如,我的程序中的第 76 行显然是一个 for 循环,第 95 行是一个右大括号,第 110 行是一个变量定义。行号应该被解释为“最接近指定行号的循环”,还是以其他方式?

这是因为代码已经过优化,所以行号可能有点偏离,尽管它应该对应于编译器反馈消息中的行号(-Minfo=accel)。所以“最接近的循环......”选项应该是正确的。

于 2017-09-18T18:35:44.303 回答