- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有std::vector<double> X,Y
两种尺寸 N
(用 N%16==0
)我想计算 sum(X[i]*Y[i])
.这是融合乘加 (FMA) 的经典用例,它在支持 AVX 的处理器上应该很快。我知道我所有的 objective-c PU 都是 Intel、Haswell 或更新的。
如何让 GCC 发出该 AVX 代码? -mfma
是解决方案的一部分,但我需要其他开关吗?
并且是std::vector<double>::operator[]
阻碍这个?我知道我可以改变
size_t N = X.size();
double sum = 0.0;
for (size_t i = 0; i != N; ++i) sum += X[i] * Y[i];
到
size_t N = X.size();
double sum = 0.0;
double const* Xp = &X[0];
double const* Yp = &X[0];
for (size_t i = 0; i != N; ++i) sum += Xp[i] * Yp[i];
所以编译器可以发现 &X[0]
在循环中不会改变。但这是否足够甚至是必要的?
当前编译器是 GCC 4.9.2、Debian 8,但如果需要可以升级到 GCC 5。
最佳答案
你看过程序集了吗?我把
double foo(std::vector<double> &X, std::vector<double> &Y) {
size_t N = X.size();
double sum = 0.0;
for (size_t i = 0; i <N; ++i) sum += X[i] * Y[i];
return sum;
}
进入http://gcc.godbolt.org/并使用 -O3 -mfma
查看 GCC 4.9.2 中的程序集,我明白了
.L3:
vmovsd (%rcx,%rax,8), %xmm1
vfmadd231sd (%rsi,%rax,8), %xmm1, %xmm0
addq $1, %rax
cmpq %rdx, %rax
jne .L3
所以它使用了fma。但是,它不会对循环进行矢量化(sd
中的 s
表示单浮点(即未压缩),d
表示双浮点)。
要对循环进行矢量化,您需要启用关联数学,例如使用 -Ofast
。使用 -Ofast -mavx2 -mfma
给出
.L8:
vmovupd (%rax,%rsi), %xmm2
addq $1, %r10
vinsertf128 $0x1, 16(%rax,%rsi), %ymm2, %ymm2
vfmadd231pd (%r12,%rsi), %ymm2, %ymm1
addq $32, %rsi
cmpq %r10, %rdi
ja .L8
所以现在它是矢量化的(pd
表示压缩 double )。但是,它没有展开。这是目前 GCC 的限制。由于依赖链,您需要展开多次。如果您想让编译器为您执行此操作,请考虑使用展开四次的 Clang,否则使用内部函数手动展开。
请注意,与 GCC 不同,Clang 默认情况下不使用 -mfma
的 fma。为了在 Clang 中使用 fma,请使用 -ffp-contract=fast
(例如 -O3 -mfma -ffp-contract=fast
)或 #pragma STDC FP_CONTRACT ON
或使用例如启用关联数学-Ofast
如果您想使用 Clang 对循环进行矢量化,无论如何您都需要启用关联数学。
参见 Fused multiply add and default rounding modes和 https://stackoverflow.com/a/34461738/2542702有关使用不同编译器启用 fma 的更多信息。
GCC 创建了很多额外的代码来处理错位,并且 N
不是 8 的倍数。您可以告诉编译器使用 __builtin_assume_aligned
和使用 N & -8
以下代码带有-Ofast -mavx2 -mfma
double foo2(double * __restrict X, double * __restrict Y, int N) {
X = (double*)__builtin_assume_aligned(X,32);
Y = (double*)__builtin_assume_aligned(Y,32);
double sum = 0.0;
for (int i = 0; i < (N &-8); ++i) sum += X[i] * Y[i];
return sum;
}
生成以下简单程序集
andl $-8, %edx
jle .L4
subl $4, %edx
vxorpd %xmm0, %xmm0, %xmm0
shrl $2, %edx
xorl %ecx, %ecx
leal 1(%rdx), %eax
xorl %edx, %edx
.L3:
vmovapd (%rsi,%rdx), %ymm2
addl $1, %ecx
vfmadd231pd (%rdi,%rdx), %ymm2, %ymm0
addq $32, %rdx
cmpl %eax, %ecx
jb .L3
vhaddpd %ymm0, %ymm0, %ymm0
vperm2f128 $1, %ymm0, %ymm0, %ymm1
vaddpd %ymm1, %ymm0, %ymm0
vzeroupper
ret
.L4:
vxorpd %xmm0, %xmm0, %xmm0
ret
关于gcc - 我需要做什么才能让 GCC 4.9 认识到使用 AVX FMA 的机会?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35439254/
Closed. This question does not meet Stack Overflow guidelines。它当前不接受答案。 想改善这个问题吗?更新问题,以便将其作为on-topic
我有 2 个不同的 View 设置 View 和默认 View 我无法将 uiswitch 值传递给默认 View 开关在 NSUserDefaults 中存储位置 设置 View .m - (voi
我猜大多数内置的随机生成器会返回类似这样的内容: [0.0, 1.0) 所以如果我想要 50% 的机会,我会使用这样的东西: if random() < .5 或类似的东西: if random()
有没有办法使用合作伙伴 WSDL 创建机会?我在网上看到的唯一示例是使用 Enterprise WSDL 创建,但它们特定于组织。 在我提到的其他链接中.. http://www.salesforce
背景 我正在使用支持向量机对不平衡类进行二元分类(即我的训练集中正负标签的比例约为 100)。我想优化以下参数:m(我从训练数据中采样的正标签与负标签的比率)、w(类权重)和 SVM 参数 C。 问题
我想根据百分比随机生成 YES 或 NO 所以我想“滚动”并有 25% 的机会击中 YES,75% 的机会击中 NO 是否希望有人能为我指出正确的方向,以最好的方式做到这一点,也许是一些文章或其他什么
我是一名优秀的程序员,十分优秀!