OpenACC内核在常见GPU上的效率是什么?

时间:2017-03-11 23:51:21

标签: c++ openacc

关于OpenACC内核在常见GPU和寄存器上失去效率的代码复杂性,共享内存操作或其他一些方面会开始阻碍性能?

还有一点,转移到GPU和核心的任务和开销太少会成为瓶颈吗?

缓存大小和代码是否适合表示每个内核或其他什么的最佳任务?

关于每个内核的OpenACC开销与潜在性能相比有多大?它是否因各种指令而有很大不同?

1 个答案:

答案 0 :(得分:1)

我不会将代码的复杂性用作性能指标。您可以在GPU上高效运行高度复杂的代码,并且运行简单的代码很差。相反,我会考虑以下因素:

  1. 设备和主机之间的数据移动。限制数据移动的频率并尝试以连续的块传输数据。使用OpenACC非结构化数据区域来匹配设备上的主机分配(即,在通过“new”或“malloc”分配数据的同时使用“输入数据”)。尽可能多地将计算移动到GPU,并且在绝对必要时仅使用OpenACC更新指令来同步主机和设备数据。如果数据移动不可避免,请使用“async”子句调查数据移动与计算机的交错。
  2. 设备上的数据访问并限制内存分歧。一定要有数据布局,以便在向量上连续访问数组的stride-1(连续)维度。
  3. 具有高计算强度,即计算与数据移动的比率。计算越多,数据移动越少越好。但是,如果存在其他高强度环路,则较低的计算强度环路很好,并且将数据移动到主机的成本将抵消在设备上运行内核的成本。
  4. 避免在设备上分配数据,因为它会强制线程序列化。这包括使用Fortran“自动”数组,并在其构造函数中声明包含分配的C ++对象。
  5. 避免原子操作。与主机原子相比,原子操作实际上非常有效,但如果可能的话仍然应该避免。
  6. 避免子程序调用。尽可能尝试内联例程。
  7. 占有。占用率是指GPU上可能运行的线程数与可能运行的最大线程数之比。请注意,100%的入住率并不能保证高性能,但如果可能的话,您应该尽量超过50%。占用限制器是每个线程(向量)使用的寄存器数量和每个块(组合)使用的共享存储器。假设您正在使用PGI编译器,您可以通过运行PGI“pgaccelinfo”实用程序来查看设备的限制。使用的寄存器数量取决于所使用的本地标量的数量(由程序员明确声明,以及编译器为保持中间计算而创建的临时数据),并且使用的共享内存量将由OpenACC“缓存”和“私有”确定“在”gang“循环中使用”private“时的指令。您可以通过添加标志“-ta = tesla:ptxinfo”来查看每个内核使用的程度。您可以通过“-ta = tesla:maxregcount:”限制每个线程使用的寄存器数量。减少寄存器的数量会增加占用率,但也会增加寄存器溢出的次数。溢出只要它们只溢出到L1 / L2缓存就可以了。溢出全球记忆将损害表现。遭受较低的占用率往往比溢出全球记忆更好。
  8. 请注意,我强烈建议您使用分析器(PGPROF,NVprof,Score-P,TAU,Vampir等)来帮助发现程序的性能瓶颈。