zoukankan      html  css  js  c++  java
  • OpenACC指令适不适合我的程序吗?

    感谢您对指令编译器感兴趣。这个文档将会真正帮助你理解您的代码是否可以从PGI加速编译器上获得好处,以及如何在GPU上使用这些指令。

    对于NVIDIA GPU不得不知道的两件事情

    1. NVIDIA GPU可以并行使用数百个计算内核来进行大规模海量数据计算。

    2. 当数百个内核进行几十万甚至上百万计的并行执行线程时,NVIDIA GPU的性能会最佳。

    将Amdahl定律应用于你的代码
    了解您的应用程序运行时配置文件是必不可少的,这决定了这些GPU上的指令是否适合您。如果应用程序运行时不是由数据密集型计算占主导,那么GPU是不适合你。但是,如果应用程序运行时是由一些计算密集型部分消耗,那么GPU显著提速。

    <IGNORE_JS_OP>什么程序适合指令.jpg

    尽管GPU的显著加速了第一个应用程序的并行部分,但运行时(run-time)的性能只提高40%,因为非并行的部分相对大。第二个应用程序GPU加速明显,因为并行部分支配初始运行时,GPU可以对整个应用程序的性能产生重大影响。



    可以用指令的代码结构

    对于PGI指令,并行表示的是并行循环。一个适合于GPU指令的程序上,将有一个或多个具有非常大的总迭代计数的并行循环。如果有一个单一的数千迭代的并行循环,你的代码可以有效地利用GPU数百个内核的优势。如果循环限制小,嵌套并行循环是必要的,以确保有足够的并行。

    提示#1

    循环体可以相对较大,运行数百甚至上千行嵌套循环体和复杂的表达式,然而循环限制必须为规则的


    至少有一些将要被加速的循环必须是完全的数据并行,这意味着没有同步,或者说迭代之间不会相互依赖.有一些嵌套里将要被加速的循环可以要求有限的同步,只要他们在传统意义上是可以矢量化的,比如reduction循环可以被加速.
    Hint #2
    完全的数据并行= 没有同步或者迭代间的相互依赖


    不适合用指令的代码结构

    不适合用PGI指令进行GPU加速的代码区和循环包括:

    -非基于循环、面向对象的或分支密集型代码

    -不是并行化或向量化的循环

    -不直接进行内存访问的循环

    -条件循环会产生重大分歧的代码路径

    -执行非结构化积累(unstructured accumulations)的循环(简单结构化积累诸如dot产品是OK的)

    -其源代码的预编译库中的函数调用的循环是PGI Accelerator编译器不可见的。

    -有I / O语句的循环

    -循环里有分支循环进入或离开,或有返回语句。

    -有Fotran STOP语句的循环

    强烈推荐的编码准则

    如果一个应用程序在源代码中有一些独立的计算密集的部分,它更容易加快在GPU上。如果应用的性能分布比较均匀(大量独立函数中每个都占了很小的比例),就需要访问大部分源码,而且可能适用于利用指令对这些源码进行加速.

    Hint #3

    对于性能稳定的应用程序,利用PGI加速编程模块的deviceresident data功能可以通过内核,甚至主机子程序边界在设备内存里保留大的数据结构

    下面是利用CFortran进行编程的通用准则:

    1.尽量避免计算数组索引(index)

    2. 用简单的表达式作为数组的下标

    3. 在将卸载的代码区域里所有函数的调用必须自动被PGI加速编译器内联,或者被程序员手动内联。

    4. 条件语句是OK的,但要警惕分支语句。

    5.将要卸载的循环必须有规则的循环限制,以及有不变的行程记数

    6.在C里,循环只能用于以下数据类型:整数、浮点、双精度或者结构体(嵌套的数据结构不能卸载到GPU

    7.在C里,用于在循环里访问数组的指针,必须被C99 restrict声明

    Hint #4

    在C语言里通常在单精度计算里,如果没有将常量定义成双精度的(比如,3.14159f),就会作为字面常量(如:3.14159),在这种情况下,标准C需要常量被当作成双精度,而且跟它相关的计算都需要变成双精度。

    在C语言中,一个常见的语句是把一个变量保存在一个标量里,为了后面重复使用.例如,你没有这些写:

      for( i = 0; i < n-1; ++i ){

       b = a + a[i+1];

      }

    而是,你可能试图使用一个标量在循环中提取一个数组

      x = a[0];

       for( i = 0; i < n-1; ++i ){

         y = a[i+1];

         b = x + y;

       x = y;

      }

    这样的一个微优化在C编程里很常见,但是第二个公式对于标量变量X有一个独立的循环。X值在一个迭代中被指派,然后用到下一个迭代中,这样这些迭代就不再是独立的。原始循环原本是完全并行的,这样问题就不是在算法,而是程序使用的编程风格。

    Hint #5

    在移植C代码,你可能碰上上面这个例子(如上述),可以有效地利用指令改变编码风格。如需例子看到http://www.pgroup.com/lit/articles/insider/v1n2a1.htm

    Fortran里,只有嵌套循环可以加速——没有array syntax, 没有 reshape(), 通常,最好避免外来F90/F2003 功能。循环加速只能对于这些数据类型:整数、real、双精度、complex, double complexderived types, allocatables, 以及CUDA数据。指针属性是不支持的,指针数组需要定义,但是指针关联是不会在GPU内存里保留。支持大多数标量运算和超越的内在函数,MAX(),SUM()

    那么现在做什么?

    你现在已经确认您程序中计算密集的部分可以用指令来进行GPU加速,那么现在就开始吧.

      一个完整的PGI Accelerator指令语法规范,请参阅
    http://www.pgroup.com/lit/whitepapers/pgi_accel_prog_model_1.3.pdf

  • 相关阅读:
    2021找工作总结
    HashMap源码(JDK1.8)-手动注释
    HashMap底层源码分析-手动注释
    面试常问的ArrayQueue底层实现
    SVN使用方法
    async await Task 使用方法
    视觉设备说明
    Java8--lambda表达式与函数式编程
    重磅!微软发布 vscode.dev,把 VS Code 带入浏览器!
    解决Vite-React项目中js使用jsx语法报错的问题
  • 原文地址:https://www.cnblogs.com/gpus/p/2441433.html
Copyright © 2011-2022 走看看