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

  • 相关阅读:
    Codeforces Round #592 (Div. 2)C. The Football Season(暴力,循环节)
    Educational Codeforces Round 72 (Rated for Div. 2)D. Coloring Edges(想法)
    扩展KMP
    poj 1699 Best Sequence(dfs)
    KMP(思路分析)
    poj 1950 Dessert(dfs)
    poj 3278 Catch That Cow(BFS)
    素数环(回溯)
    sort与qsort
    poj 1952 buy low buy lower(DP)
  • 原文地址:https://www.cnblogs.com/gpus/p/2441433.html
Copyright © 2011-2022 走看看