- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在编写一些 AVX 代码,我需要从可能未对齐的内存中加载。我目前正在加载 4 个 double ,因此我将使用内部指令 _mm256_loadu_pd ;我写的代码是:
__m256d d1 = _mm256_loadu_pd(vInOut + i*4);
-O3 -mavx -g
随后使用 objdump 获取汇编代码以及带注释的代码和行(
objdump -S -M intel -l avx.obj
)。当我查看底层汇编代码时,我发现以下内容:
vmovupd xmm0,XMMWORD PTR [rsi+rax*1]
vinsertf128 ymm0,ymm0,XMMWORD PTR [rsi+rax*1+0x10],0x1
vmovupd ymm0,XMMWORD PTR [rsi+rax*1]
gcc (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0
在 Ubuntu 18.04 x86-64 上。
最佳答案
GCC 的默认调优 ( -mtune=generic
) 包括 -mavx256-split-unaligned-load
和 -mavx256-split-unaligned-store
,因为在某些情况下,当内存在运行时实际上未对齐时,这会在某些 CPU(例如第一代 Sandybridge 和某些 AMD CPU)上提供较小的加速。
使用 -O3 -mno-avx256-split-unaligned-load -mno-avx256-split-unaligned-store
如果你不想要这个,或者更好,使用 -mtune=haswell
. 或使用 -march=native
为您自己的计算机进行优化。没有“通用 avx2”调整。 ( https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html )。
英特尔 Sandybridge 将 256 位加载作为单个 uop 运行,在加载端口中需要 2 个周期。 (与 AMD 将所有 256 位向量指令解码为 2 个单独的 uops 不同。)Sandybridge 存在未对齐的 256 位加载问题(如果地址在运行时实际上未对齐)。我不知道细节,也没有找到关于减速究竟是什么的具体信息。也许是因为它使用了带 16 字节存储体的存储缓存?但是 IvyBridge 可以更好地处理 256 位负载,并且仍然具有存储缓存。
根据 GCC 邮件列表中关于实现选项 ( https://gcc.gnu.org/ml/gcc-patches/2011-03/msg01847.html ) 的代码的消息,“ 将某些 SPEC CPU 2006 基准测试的速度提高了 6%。”(我认为这是针对 Sandybridge,只有当时存在的 Intel AVX CPU。)
但是,如果内存在运行时实际上是 32 字节对齐的,那么即使在 Sandybridge 和大多数 AMD CPU 上,这也是纯粹的缺点1 .因此,使用此调整选项,您可能会因为未能将对齐保证告知编译器而蒙受损失。如果你的循环大部分时间运行在对齐的内存上,你最好至少用 -mno-avx256-split-unaligned-load
编译那个编译单元。或暗示这一点的调整选项。
在软件中拆分总是会产生成本。让硬件处理它使对齐的情况非常有效(除了 Piledriver1 上的存储),未对齐的情况可能比某些 CPU 上的软件拆分慢。所以这是一种悲观的方法,如果数据真的很可能在运行时没有对齐,而不是在编译时不能保证总是对齐,那么这是有道理的。例如也许您有一个大部分时间都使用对齐缓冲区调用的函数,但您仍然希望它适用于使用未对齐缓冲区调用的罕见/小情况。在这种情况下,即使在 Sandybridge 上,拆分加载/存储策略也是不合适的。
缓冲区通常是 16 字节对齐但不是 32 字节对齐,因为 malloc
在 x86-64 glibc(和 libstdc++ 中的 new
)上返回 16 字节对齐的缓冲区(因为 alignof(maxalign_t) == 16
)。对于大缓冲区,指针通常在页面开始后 16 个字节,因此对于大于 16 的对齐总是未对齐。使用 aligned_alloc
反而。
请注意 -mavx
和 -mavx2
根本不要更改调整选项 :gcc -O3 -mavx2
仍然适用于所有 CPU,包括那些不能实际运行 AVX2 指令的 CPU。这非常愚蠢,因为如果针对“平均 AVX2 CPU”进行调整,您应该使用单个未对齐的 256 位负载。不幸的是 gcc 没有选择这样做,而且 -mavx2
并不意味着 -mno-avx256-split-unaligned-load
或任何东西。 见 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80568和 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78762对于具有指令集选择影响调整的功能请求 .
这就是为什么你应该使用 -march=native
制作本地使用的二进制文件,或者 -march=sandybridge -mtune=haswell
制作可以在各种机器上运行的二进制文件,但可能主要在具有 AVX 的较新硬件上运行。 (请注意,即使 Skylake Pentium/Celeron CPU 也没有 AVX 或 BMI2;可能在 256 位执行单元或寄存器文件的上半部分有任何缺陷的 CPU 上,它们禁用 VEX 前缀的解码并将它们作为低端奔腾。)
gcc8.2 的调优选项如下。 ( -march=x
意味着 -mtune=x
)。 https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html .
我查了 on the Godbolt compiler explorer通过编译 -O3 -fverbose-asm
并查看评论,其中包括所有隐含选项的完整转储。我包括 _mm256_loadu/storeu_ps
函数,以及一个可以自动向量化的简单浮点循环,所以我们也可以看看编译器做了什么。
使用 -mprefer-vector-width=256
(gcc8) 或 -mno-prefer-avx128
(gcc7 及更早版本)覆盖调整选项,如 -mtune=bdver3
并根据需要获得 256 位自动矢量化,而不仅仅是手动矢量化。
-mtune=generic
: 两者 -mavx256-split-unaligned-load
和 -store
.可以说随着 Intel Haswell 越来越不合适,后来变得越来越普遍,我认为最近 AMD CPU 的缺点仍然很小。尤其是拆分未对齐的负载,AMD 调整选项无法启用这些负载。 -march=sandybridge
和 -march=ivybridge
: 分开两个。 (我想我已经读过 IvyBridge 改进了对未对齐的 256 位加载或存储的处理,因此它不太适合在运行时可能对齐数据的情况。)-march=haswell
及更高版本:均未启用拆分选项。 -march=knl
: 没有启用拆分选项。 (Silvermont/Atom 没有 AVX)-mtune=intel
: 没有启用拆分选项。即使使用 gcc8,使用 -mtune=intel -mavx
自动矢量化选择达到读/写目标数组的对齐边界,这与 gcc8 仅使用未对齐的常规策略不同。 (同样,另一个总是有成本的软件处理案例,而不是让硬件处理异常(exception)情况。)-march=bdver1
(推土机):-mavx256-split-unaligned-store
,但不加载。-mprefer-avx128
(自动矢量化将仅使用 128 位 AVX,但内在函数当然仍然可以使用 256 位矢量)。 -march=bdver2
(打桩机), bdver3
(压路机),bdver4
(挖掘机)。和推土机一样。他们自动矢量化一个 FP a[i] += b[i]
使用软件预取和足够的展开循环,每个缓存行只预取一次! -march=znver1
(禅):-mavx256-split-unaligned-store
但不加载,仍然只使用 128 位自动矢量化,但这次没有 SW 预取。 -march=btver2
( AMD Fam16h, aka Jaguar ):既没有启用拆分选项,也没有像推土机系列那样自动矢量化,只有 128 位矢量 + SW 预取。 -march=eden-x4
(通过带有 AVX2 的 Eden):既没有启用拆分选项,也没有启用 -march
选项甚至不启用 -mavx
和自动矢量化使用 movlps
/movhps
8 字节加载,这真的很愚蠢。至少使用 movsd
而不是 movlps
打破虚假的依赖。但是如果你启用 -mavx
,它使用 128 位未对齐的加载。这里真的很奇怪/不一致的行为,除非有一些奇怪的前端。vmovaps [mem], ymm
根据 Agner Fog 的 microarch pdf (
https://agner.org/optimize/),每 17 到 20 个时钟运行一个对齐的商店。此效果在推土机或压路机/挖掘机中不存在。
vmovaps ymm
指令仍然只受益于推土机系列上低 128 位的移动消除。
-march=native
构建的奢侈。在每个目标架构上,因此在制作可以在任何支持 AVX 的 CPU 上运行的二进制文件时需要权衡。只要在其他 CPU 上没有灾难性的缺点,在某些 CPU 上使用 256 位代码获得大幅加速通常是值得的。
vinsertf128 ymm, [mem], 1
在 Haswell/Skylake 的端口 5 上不需要 shuffle 单元:它可以在任何向量 ALU 端口上运行。 (而且它没有微熔断器,因此需要 2 uop 的前端带宽。)
-O2
或
-O3
编译的,这个选项无论如何只会影响 AVX 代码生成。但不幸的是,许多人使用
-O3 -mavx2
而不是
-O3 -march=native
。所以他们可能会错过 FMA 、BMI1/2、popcnt 以及它们的 CPU 支持的其他东西。
关于gcc - 为什么 gcc 不将 _mm256_loadu_pd 解析为单个 vmovupd?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52626726/
我正在尝试在 Conda 环境中编译一些代码,在那里我 之前安装的编译包gcc_linux-64 . 然而,即使在停用和重新激活环境之后,gcc还在/usr/bin/gcc . 我该怎么做才能让 Co
关闭。这个问题是opinion-based .它目前不接受答案。 想要改进这个问题? 更新问题,以便 editing this post 可以用事实和引用来回答它. 关闭 7 年前。 Improve
这其实是两个问题: 1 - 在我的 debian amd64 系统上,我似乎无法构建与 gmp/mpfr/mpc 动态链接的交叉 GCC。即使我删除 --disable-shared,它也总是静态链接
研究ELF格式的结果,可以看到目标文件中有一个符号对应每个函数,对应的符号表项的值为st_size,表示大小的功能。 问题是,即使我更改了目标文件中特定函数的 st_size 并链接了它,但可执行文件
海湾合作委员会的 documentation for #line directives说他们是这样的: #line "myfile.cpp" 123 但是当我用 g++ 5.1 检查输出时,它们实际上
我正在使用 as 和 gcc 来汇编和创建 ARM 汇编程序的可执行文件,正如 this 所推荐的那样教程,如下: 给定一个汇编源文件,program.s,我运行: as -o program.o p
long long x; double n; x=long long(n); 这不起作用。什么是正确的方法? 最佳答案 显而易见的: x = (long long) n; 关于gcc - 转换为长长
我想知道用于 gcc 的原子内置函数的头文件是什么? 我想使用这 2 个函数为我当前创建的线程库实现互斥锁。 bool __sync_bool_compare_and_swap (type *ptr,
它出现在 another question :gcc调用的程序和部件是什么? (特别是在编译 C 或 C++ 时)以便有人可以设计一些拦截和更改流程的方案以用于各种自定义编码目的? 最佳答案 编译器二
可能吗?我想使用 gcc喜欢 assembler并在将其编译为 ubuntu 上的可执行文件后。 我尝试过这个: gcc a.asm -o out.o 来自 out.o文件编译成.out可执行文件。
我写了一个简单的 C 程序 test.c : #include #include int add(int a, int b); int main() { int i=5,j=10;
即。所以如果你使用任何八进制文字,它会给你一个警告。 微软编译器的同样问题。 如果没有,是否有任何其他工具可以检测八进制文字。 (vim 似乎有一个很酷的技巧,它突出了第一个领先的将不同的颜色归零,但
我在旧线程中搜索。但没有找到任何线程回答我的问题。 gcc 是否像 vc++ 一样支持函数级链接? 如果是,我应该提供什么选项来链接目标文件和库? 最佳答案 看起来 gcc 不直接支持函数级链接。您可
也许标题并没有把问题说得那么准确:我知道当我运行 gcc foo.c 时,GCC 会调用其他为它完成所有工作的子程序,从而生成主 gcc 程序只是一个界面。但这究竟是如何完成的呢? 它是否使用syst
我听说最近版本的 gcc 非常擅长将通过函数指针的调用转换为直接调用。但是,我在网上或快速浏览 gcc 的源代码上找不到任何关于它的信息。有谁知道这是否真的是真的,如果是这样,它使用什么算法来做到这一
gcc/g++ 链接器选项“-Map”生成的“.map”文件用于什么? 以及如何阅读它们? 最佳答案 我建议为您投入生产的任何软件生成一个映射文件并保留一份副本。 它可用于破译崩溃报告。根据系统的不同
gcc信息文件在有关x86-64特定标志的部分中说 其他事情: There is no `-march=generic' option because `-march' ind
我想知道 gcc 链接器选项(例如:-Wl,options)是否可以更改编译后的可执行文件中的汇编指令,因为如果您使用某些 gcc 优化选项会发生这种情况? 当您比较编译后的二进制文件(例如比较签名)
是否有GCC编译指示会停止,暂停或中止编译过程? 我正在使用gcc 4.1,但也希望在gcc 3.x版本上也可以使用该编译指示。 最佳答案 您可能需要#error: edd@ron:/tmp$ g++
当我使用gcc编译C程序时我通常使用 -g 将一些调试信息放入 elf 文件中这样 gdb 就可以在需要时帮助我。 但是,我注意到有些程序使用 -ggdb,因为它应该使调试信息对 gdb 更加友好。
我是一名优秀的程序员,十分优秀!