首页 > 其他 > 详细

《编译优化之 - 向量化优化入门》

时间:2020-08-26 15:32:00      阅读:270      评论:0      收藏:0      [点我收藏+]

 

 


编译器

GCC ICC AOCC LLVM编译器相关
关注数:1 文章数:17 访问量:9651
 

作者:zhugl0

这个作者很懒,什么都没留下…
    • 原创 GCC - 无效代码删除优化

      前言   无效代码删除(DCE)是一种广泛使用的编译优化技术,它的目的是删除程序中不会影响程序运行的代码和变量,减少代码体积,更好地促使其它相关优化的进行,以提高程序效率,特别是在一些对资源受限的嵌入式设备上,使用无效代码删除操作来减少代码体积是非常重要的。数据流分析技术的发展,许多传统优化问题有了成熟的解决方案,无效代码删除优化也越发高效稳定。 对于以下示例: #include<stdio.h> void func(); void a() { int i = 0; for
      2020-06-25 21:07:28 技术分享图片183 技术分享图片0
    • 原创 GCC添加优化选项控制新建的pass

      前言   GCC中包含了从-O0到-O3以及-Og,-Os和-Ofast各种级别的优化,并提供了上百多个可独立控制的优化标志。每个优化级别都启用了优化标志的子集,并在启用调试信息生成对可执行代码没有任何影响。但是确定何时运行pass是一个复杂的过程,每一个pass都有一个门函数(gate function), 它根据优化级别和标志来决定是否运行该pass。   GCC中如何添加一个优化pass的操作,可以参考《GCC - GIMPLE IR 学习一》。如何通过优化选项控制我新添加的优化pass?在回答这个问
      2020-06-23 15:31:53 技术分享图片85 技术分享图片0
    • 原创 struct的内存对齐

        结构体字节对齐能减少内存占用,提高内存访问效率。不论在x86或ARM处理器上C的每种类型存储都会要求内存对齐,除char以外。结构体中不能包含结构体本身,但可以包含指针。由于平台原因对齐大小不同,可能同一个结构体得到的大小会不同,但一般的对齐规则如下: chars可以从任何字节地址开始,2字节shorts必须从偶数地址开始,4字节的ints或floats必须从被4整除的地址开始,而8字节的l...
      2020-05-02 17:11:53 技术分享图片69 技术分享图片0
    • 原创 AMD AOCC安装

      AOCC是AMD的一款商用编译器,也称为AMD Optimizing C/C++ Compiler,官网地址为:https://developer.amd.com/amd-aocc/ 。 目前的最新版是AOCC 2.1版本,它基于LLVM 9.0版本,它针对AMD系列17h处理器进行了调整;对部分AMD的机型进行了优化;优化了AMD LibM等库;LLVM链接器(lld)作为默认链接器,不再需要G...
      2020-05-01 20:44:40 技术分享图片729 技术分享图片0
    • 原创 LLVM 9.0 Clang、Flang及工具的详细安装过程

        LLVM 10.0.0是当前的最新版,从2020/3/24开始提供下载,在此记录的是LLVM 9.0.0版本的安装,其发布时间是2019/9/19,前端clang版本是9.0.0。由于安装的时候属于最新版本,前端只能安装Clang,为了安装Flang前端,遇到太多的问题,踩了太多的坑,以至于当时我们两个人搞了好几天才安装上,在此记录一下安装过程和注意事项,并且感谢当时和我一起安装软件的师兄! ...
      2020-04-28 00:36:15 技术分享图片1107 技术分享图片3
    • 原创 GCC - GIMPLE IR学习之pass

        源码经过GCC前端的词法/语法、语义分析之后,生成AST/GENERIC,再转换为前端语言无关的中间表示GIMPLE,之后GCC再对GIMPLE进行GIMPLE低级化、构建cfg等一系列处理,这一系列操作称为GCC Pass(处理过程)。每个pass完成一种处理,其输出结果作为下一个pass的输入。在此以gcc-8.2.0的源码为例说明。 GCC中所有的pass组织在passes.def链表中...
      2020-04-26 00:36:02 技术分享图片148 技术分享图片0
    • 原创 编译优化之 - 预取优化入门

      前言   预取是在处理器实际需要之前,将指令或数据从较慢的内存中提取到较快的cache中,来最大程度地减少cache未命中的延迟。预取器通常能预测下一个使用的缓存行,将他们载入缓存,但是也容易出错导致缓存污染,并给内存子系统带来额外的压力。在高性能处理器中,处理高速缓存未命中或延迟以及正确管理内存带宽,预取是比较有用的方法。在分布式共享内存(DSM)系统中,远程内存访问比本地访问花费更长的时间,因...
      2020-04-25 13:49:12 技术分享图片602 技术分享图片2
    • 原创 使GCC变得可调试

      默认安装的GCC使用的是-O2 -g,在对GCC进行调试的时候很多变量已经被优化掉了,跟踪不了。如下所示: (gdb) p *name value has been optimized out 为了使GCC变得可调试,需要做以下修改: 进入编译GCC的目录,即执行../configure CFLAGS="-g3 -gdwarf-2 -O0" CXXFLAGS="-g3 -gdwarf-2 -...
      2020-04-24 12:24:03 技术分享图片142 技术分享图片0
    • 原创 jemalloc安装和使用

      前言   jemalloc是一个内存分配器,最开始出现在FreeBSD上的libc中,FreeBSD最早使用phkmalloc,但它不是在多处理器系统且支持多线程的情况下设计的,为了解决多处理器系统和多线程应用程序的可扩展性瓶颈,由此诞生jemalloc,它是Jason Evans 2005年进行开发的,因此叫"je"。在2007年的时候为了改善Firefox在3.0版中的内存使用情况,使用jem...
      2020-04-13 16:21:24 技术分享图片733 技术分享图片0
    • 原创 GCC - 添加ipa pass

      关于ipa的介绍和基本使用,在之前的博客中:编译优化之 - 过程间优化(IPA/IPO)入门。这里主要是记录一下gcc-8.2.0版本中新建一个ipa pass的过程。 进入gcc-8.2.0/gcc目录,新建ipa-test.c文件。代码可参考ipa-*.c那些pass中的过程进行修改,在此参考ipa-hsa.c文件,其代码较少。拷贝头文件到ipa-test.c #include "conf...
      2020-04-12 21:13:51 技术分享图片90 技术分享图片0
    • 原创 GCC - GIMPLE IR 学习一

      前言   GIMPLE是从AST/GENERIC转换而来的三地址表示形式,它是一种与前端语言无关的中间表示,引入了临时变量来保存中间值。GIMPLE的生成分为高级GIMPLE(High-Level GIMPLE)和低级GIMPLE(Low-Level GIMPLE)两个阶段。   AST/GENERIC为树形结构,其节点属性较多,包含详细的功能信息,但由于其与前端语言相关缺乏通用性、结构复杂不是线...
      2020-04-11 19:40:21 技术分享图片370 技术分享图片3
    • 原创 编译优化之 - 向量化优化入门

      1. 介绍 2. Intel高级向量扩展 3. GCC中向量化 4. ICC中向量化 5. AOCC/LLVM中向量化 1. 介绍 什么是自动向量化?   自动向量化(automatic vectorization)是自动并行化(automatic parallelization)的一种特殊情况,它将一次处理一对的标量运算转换为一次并行处理多对的向量运算。因此向量化可以显着加速一些带循环的...
      2020-03-30 16:52:25 技术分享图片1069 技术分享图片1
    • 原创 编译优化之 - 常量传播入门

      1. 介绍   常量传播是现代的编译器中使用最广泛的优化方法之一,它通常应用于高级中间表示(IR)。它解决了在运行时静态检测表达式是否总是求值为唯一常数的问题,如果在调用过程时知道哪些变量将具有常量值,以及这些值将是什么,则编译器可以在编译时期简化常数。 常量传播在优化中的几种用途: 能在编译时求值的表达式不需要在执行时才求值。如果这样的表达式在循环内,则只需要在编译时进行一次求值而节省执行时间...
      2020-03-19 19:34:25 技术分享图片612 技术分享图片0
    • 原创 编译优化之 - 过程间优化(IPA/IPO)入门

      过程间分析(inter-procedural analysis)是一个多步骤的过程,是LTO分析过程中的重要部分,也是一个跨模块的分析过程。跨模块的优化功能实现最早在1987年(Link time optimization),后来相继出现了过程间分析和转换,动态链接程序的优化(IPA + LTO)。 过程间分析包含local分析和global分析。局部分析会为每一个过程和调用点生成Local Su...
      2020-01-10 20:29:45 技术分享图片649 技术分享图片0
    • 原创 编译优化之 - 链接时优化(LTO)入门

      1. 关于 LTO -flto ThinLTO LTO(Link Time Optimization)链接时优化是链接期间的程序优化,多个中间文件通过链接器合并在一起,并将它们组合为一个程序,缩减代码体积,因此链接时优化是对整个程序的分析和跨模块的优化。 flto是使用lto的主要方法,是一个优化选项,禁用lto使用-fno-lto。 ThinLTO是一种可扩展和增量式的新型LTO,与LTO相比...
      2019-12-24 13:42:14 技术分享图片2836 技术分享图片0
    • 原创 GCC简单编译流程

      gcc编译流程 gcc将hello.c源文件编译成可执行的binary文件需要经过hello.i、hello.s、hello.o、hello四个步骤,如图所示: 1.预处理:展开头文件和宏定义等。 gcc -E hello.c -o hello.i 2.编译:将预处理得到的源代码转换成汇编文件(得到汇编文件)。 gcc -S hello.i -o hello.s 3.汇编:将汇编代码转成不可执...
      2019-12-18 17:21:17 技术分享图片86 技术分享图片0
    • 原创 编译优化之 - 结构数据布局优化入门

      前言 该博客只是自己的一个关于structure优化的学习笔记,文档内容是通过网上收集的资料包括论文,加上一点自己的理解整理而成。 结构数据布局优化(Structure Data Layout Optimizations)是比较成熟也是使用广泛的编译器优化技术,旨在提高数据局部性,减少cache miss。常用的structure optimizations有:结构体拆分(structure sp...
      2019-12-18 17:16:51 技术分享图片141 技术分享图片0

 


 

 

编译优化之 - 向量化优化入门

1. 介绍
2. Intel高级向量扩展
3. GCC中向量化
4. ICC中向量化
5. AOCC/LLVM中向量化

1. 介绍

什么是自动向量化?

  自动向量化(automatic vectorization)是自动并行化(automatic parallelization)的一种特殊情况,它将一次处理一对的标量运算转换为一次并行处理多对的向量运算。因此向量化可以显着加速一些带循环的程序运算,尤其是在大型数据集上。根据arch信息,编译器优化的目标可以是Intel或AMD处理器中的SSE*、AVX/AVX2或更高级的指令,或ARM处理器中的NEON指令。
  默认情况下,GCC、ICC或AOCC/LLVM编译器中都启用了部分自动向量化功能。这些指令受运行时检查保护,即运行时检查机器是否支持该指令集,如果不支持则使用其它的指令集。

什么是SIMD指令?

  SIMD(Single instruction, multiple data)单指令多数据技术能对程序中数据进行并行处理,提高吞吐量。它将原来需要多次装载的数据一次性装载到向量寄存器,即SIMD指令允许在一个步骤中处理多个数据。现代的CPU设计都包括SIMD指令,以提高多媒体程序和科学计算程序的性能,但SIMD与利用线程的SIMT不同。SIMD指令的首次使用是在1966年,它一般分为两种:

  • 手工向量化:通过内嵌汇编码或编译器提供的内函数来添加SIMD指令。
  • 自动向量化:利用编译器分析串行程序中控制流和数据流的特征,识别程序中可以向量执行的部分,将标量语句自动转换为相应的SIMD向量语句。

机器支持哪些指令集?

cat /proc/cpuinfo
  • 1

本机cpu支持的simd指令集如下:
技术分享图片

gcc -c -Q -march=native --help=target
  • 1

本机GCC8.2支持的simd指令集如下:
技术分享图片

注意:向量化的操作需要机器硬件的支持!


2. Intel高级向量扩展

较早的相关英特尔SSE指令还支持各种有符号和无符号整数大小,包括有符号和无符号byte(B,8位),word(W,16位),doubleword(DW,32位),quadword( QW(64位)和doublequadword(DQ,128位)长度。

表1:英特尔AVX后缀标记

标记含义
[s / d] 单精度或双精度浮点
[ps / pd / sd] 打包单精度、打包双精度、标量双精度
[i / u] nnn 位大小为nnn的有符号或无符号整数,其中nnn是128、64、32、16或8
epi32 扩展打包的32位有符号整数
si256 标量256位整数

更多关于Intel Advanced Vector Extensions的信息请见:Introduction to Intel® Advanced Vector Extensions

  1. MMX指令
    MultiMedia eXtensions(MMX),MMX指令主要使用的寄存器为MM0 ~ MM7,与浮点运算不能同时进行。MMX指令能一次性地操作1个64-bit的数据、或者两个32-bit的数据、或者4个16-bit的数据、或者8个8-bit的数据。
    MMX指令集的扩展包括:3DNow!、SSE、AVX

  2. SSE指令
    Streaming SIMD eXtensions(SSE),SSE指令采用了独立的寄存器组XMM0 ~ XMM7,64位模式下为XMM0 ~ XMM15,并且这些寄存器的长度也增加到了128-bit。
    SSE指令的升级版包括:SSE2/SSE3/SSSE3/SSE4

  3. AVX/AVX2指令
    Advanced Vector eXtentions(AVX),AVX对XMM寄存器做了扩展,从原来的128-bit扩展到了256-bit,并从XMM0–XMM7重命名为YMM0–YMM7,仍可通过SSE指令对YMM寄存器的低128位进行操作。新指令使用英特尔所谓的VEX前缀进行编码,这是一个两字节或三字节的前缀,旨在消除当前和将来的x86/x64指令编码的复杂性。AVX2将大多数整数命令扩展为256位,并引入了融合的乘加(FMA)操作。

  4. FMA指令
    Fused-Multiply-Add(FMA),FMA指令集是128-bit和256-bit的SSE的扩展指令集,以进行乘加运算。共有两种变体:FMA4、FMA3,自2014年以来,从PILEDRIVER架构开始,AMD处理器就支持FMA3;从Haswell处理器和Broadwell处理器开始,英特尔则支持FMA3。

  5. AVX512*指令
    英特尔架构处理器支持旧式和现代指令集,从64位MMX扩展到新的512位指令AVX-512。ZMM的低256-bit与YMM混用。ZMM的前缀为EVEX。与AVX / AVX2相比,AVX-512最显着的新功能是512位矢量寄存器宽度。

  6. 其他指令
    KNC等其他指令集。

Intel不同架构向量化指令集如下:

技术分享图片

表2: 部分FMA指令说明

指令含义
VFMADD[z][P/S][D/S] 乘法加法融合指令:A = r1 * r2 + r3(packed/scalar of double/single)
VFMSUB[z][P/S][D/S] 乘法减法融合指令:A = r1 * r2-r3(packed/scalar double/single)
VFNMADD[z][P/S][D/S] 乘法加法融合的负指令:A = -r1 * r2+r3( packed/scalar double/single)
VFNMSUB[z][P/S][D/S] 乘法减法融合的负指令: A = -r1 * r2-r3(packed/scalar double/single)
VFMADDSUB[z]P[D/S] 乘法与加减法交替的融合指令,奇数索引:A = r1 * r2 + r3,偶数索引:A = r1 * r2-r3(packed double/single)
VFMSUBADD[z]P[D/S] 乘法与加减法交替的融合指令,奇数索引:A = r1 * r2-r3 ,偶数索引:A = r1 * r2+r3(packed double/single)

其中[z]代表字符串132或213或231,对应操作数A,B,C的使用顺序:

  • 132是A = AC + B
  • 213是A = AB + C
  • 231是A = BC + A

3. GCC中向量化

GCC8.2.0中关于向量化操作的选项有:-ftree-loop-vectorize、-ftree-slp-vectorize、-ftree-loop-if-convert、-ftree-vectorize、-fvect-cost-model=model、-fsimd-cost-model=model。前两个向量化选项默认情况下在-O3中已启用,这里不一一说明。

具体每个选项的使用及详细介绍请见:https://gcc.gnu.org/onlinedocs/gcc-8.2.0/gcc/Optimize-Options.html#Optimize-Options

3.1 示例

使用的示例代码如下:

// vect.c
int main()
{
  int N = 1000;
  int a[N], b[N], c[N];
  for (int i = 0; i < N; i++) {
    b[i]=c[i]=i;
    a[i] = b[i] + c[i];
  }

  for (int i = 0; i < N; i++) {
   a[i] = a[i] + a[i];
  }

   printf("%d\n",a[100]);
   return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

如何知道一个循环是否启用了向量化?  gcc中可使用-fopt-info-vec-optimized-fopt-info-vec命令来查看,操作如下:
技术分享图片
或使用-fopt-info-vec-all选项记录下所有信息,并保存到一个文件,方便查看,如下所示:
技术分享图片
GCC中向量化操作功能有较多限制,比如:

  • 循环中有较多条件语句,函数调用等,复杂的cfg。这样做不了向量化优化
  • 嵌套循环中,外层循环的索引参与内部循环计算,导致无法向量化优化
  • 其他一些特性

假若想显式的指定gcc采用什么向量化进行编译(前提是硬件支持),可参考如下操作:

gcc -O3 -march=core-avx2 vect.c -std=c99 -S -o vect.s
  • 1

使用-march=core-avx2指令指定采用AVX2指令集(可指定其他指令集)。部分汇编码如下:
技术分享图片


4. ICC中向量化

Intel编译器中可用一下几种方式生成向量化指令:

  • SIMD vector intrinsics
  • OpenMP* 4.0 (SIMD part)
  • Auto-vectorization
  • Inline assembly code

英特尔MIC架构向量化的最重要方面之一是数据对齐。例如向量加法操作,如果编译器不知道数据对齐方式(通常是这种情况是对齐方式不正确),则将迫使编译器生成效率较低的代码。因此,重要的是优化数据的对齐并适当地将信息传达给编译器。

更多关于循环矢量化优化程序的信息请见:https://software.intel.com/en-us/articles/program-optimization-through-loop-vectorization

4.1 示例

在此使用的icc18,和测试代码如下:

// tmp.c
#include<stdio.h>
int main()
{
   int n = 1000;
   int a[n],b[n];
   for (int i = 0; i < n; ++i)
        {
           a[i] = i * 10;
           b[i] = a[i]+i * 10;
        }
    printf("%d\n",b[10]);
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

如何知道一个循环是否启用了向量化?  icc中可使用-qopt-report -qopt-report-phase=vec命令查看,操作如下:

icc -qopt-report -qopt-report-phase=vec -O3 tmp.c -std=c99

// icc: remark #10397: optimization reports are generated in *.optrpt files in the output location

vim tmp.optrpt

// 报告结果如下
Intel(R) Advisor can now assist with vectorization and show optimization
  report messages with your source code.
See "https://software.intel.com/en-us/intel-advisor-xe" for details.


Begin optimization report for: main()

    Report from: Vector optimizations [vec]


LOOP BEGIN at tmp.c(6,4)
   remark #15300: LOOP WAS VECTORIZED
LOOP END

LOOP BEGIN at tmp.c(6,4)
<Remainder loop for vectorization>
   remark #15301: REMAINDER LOOP WAS VECTORIZED
LOOP END
===========================================================================
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

如上remark #15301: REMAINDER LOOP WAS VECTORIZED所示,icc对该代码启用了循环优化,部分汇编码如下所示:
技术分享图片
如果要求编译器不要向量化特定循环,可以使用#pragma novector命令,如下:

#pragma novector 
for (int i = 0; i < n; ++i)

//同样使用以上操作,生成报告如下
LOOP BEGIN at tmp.c(7,4)
   remark #15319: loop was not vectorized: novector directive used
LOOP END
===========================================================================
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

部分汇编码如下所示:
技术分享图片

类似命令还有:

  • #pragma vector always
  • #pragma vector align

假若想显式的指定icc采用什么向量化进行编译(前提是硬件支持),可参考如下操作:

icc -qopt-report -qopt-report-phase=vec -O3 -march=core-avx2 tmp.c -S -o tmp0.s -std=c99
  • 1

使用-march=core-avx2指令指定采用AVX2指令集(可指定其他指令集),-qopt-report -qopt-report-phase=vec记录向量化信息。部分汇编码如下:
技术分享图片


5. AOCC/LLVM中向量化

  LLVM有两种向量化:作用于循环的Loop Vectorizer、将代码中找到的多个标量合并为矢量的SLP Vectorizer。默认情况下已启用了两种向量化优化。
  AOCC2.1中向量化相关的选项有:-enable-strided-vectorization、-enable-epilog-vectorization、-vectorize-memory-aggressively、-global-vectorize-slp、-region-vectorize、-suppress-fmas。

具体每个选项的使用及详细介绍请见:https://developer.amd.com/wp-content/resources/AOCC-2.1-Clang-the%20C%20C++%20Compiler.pdf

5.1 示例

LLVM中若想禁用Loop Vectorizer和SLP Vectorizer,可以使用命令行标志通过clang禁用它:

clang ... -fno-vectorize  ohter.c
clang ··· -fno-slp-vectorize file.c
  • 1
  • 2

可以使用命令行标志“ -force-vector-width”来控制矢量化SIMD宽度:

clang  -mllvm -force-vector-width=8 ...
opt -loop-vectorize -force-vector-width=8 ...
  • 1
  • 2

可以使用命令行标志“ -force-vector-interleave”来控制展开因子:

clang  -mllvm -force-vector-interleave=2 ...
opt -loop-vectorize -force-vector-interleave=2 ...
  • 1
  • 2

以上示例及说明参考自“Auto-Vectorization in LLVM”,更多详细信息请见:https://llvm.org/docs/Vectorizers.html

在此使用以下示例代码:

// tmp.c
#include<stdio.h>
int main()
{
    int n = 1000;
    int a[n],b[n];
   for (int i = 0; i < n; ++i)
   {
        a[i] = i * 2;
        for(int j = 0; j<n/2;j++)
        {
           b[i] = a[i]+a[j]*2;
        }
   }
   printf("%d\n",b[10]);
   return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

如何知道一个循环是否启用了向量化?  llvm中可使用-Rpass-missed=loop-vectorize命令查看,操作如下:

clang -O3 -Rpass-missed=loop-vectorize tmp.c

// 得到信息如下。可知对于如上循环很多编译器是做不了向量化优化的
tmp.c:6:4: remark: loop not vectorized [-Rpass-missed=loop-vectorize]
   for (int i = 0; i < n; ++i)
   ^
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

假如使用一下代码:

#include<stdio.h>
int main()
{
   int n = 1000;
   int a[n],b[n];
   for (int i = 0; i < n; ++i)
   {
       a[i] = i * 2;
   }
   printf("%d\n",a[10]);
   return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

再使用clang -O3 -Rpass=loop-vectorize tmp.c命令查看,便得到一下结果:

tmp.c:6:4: remark: vectorized loop (vectorization width: 4, interleaved count: 2) [-Rpass=loop-vectorize]
   for (int i = 0; i < n; ++i)
   ^
  • 1
  • 2
  • 3

对于以上代码,AOCC2.1使用-region-vectoriz命令操作如下:

clang -O3 -Rpass=loop-vectorize tmp.c -flto -Wl,-mllvm -Wl,-region-vectoriz
  • 1

AOCC2.1中向量化操作与LLVM基本相似,在此不做更多介绍。


References:

  • SIMD自动向量化编译优化概述
  • https://colfaxresearch.com/skl-avx512/
  • https://en.wikipedia.org/wiki/Advanced_Vector_Extensions
  • https://llvm.org/docs/Vectorizers.html
  • https://developer.amd.com/wp-content/resources/AOCC-2.1-Clang-the%20C%20C++%20Compiler.pdf

《编译优化之 - 向量化优化入门》

原文:https://www.cnblogs.com/cx2016/p/13565280.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!