gpt4 book ai didi

c++ - 排列 AVX 寄存器的内容

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:12:40 25 4
gpt4 key购买 nike

我有一个带有四个 double 值的 AVX 寄存器。现在我需要对每个元素分别执行一些算术运算。我需要做的事情的简化如下。

Situation:
a = [a4 a3 a2 a1]
w = [ 0 0 0 w1]
x = [ 0 0 0 x1]
y = [ 0 0 0 y1]
z = [ 0 0 0 z1]

Desired result:
w = [-- -- -- w1+a1]
x = [-- -- -- x1+a2]
y = [-- -- -- y1+a3]
z = [-- -- -- z1+a4]

除了期望的结果不仅仅是两个值的总和,而是它们的更复杂的算术表达式。我把 -- 放在哪里,我的意思是我不关心那些值,它们将被丢弃。

我发现我可以使用置换操作置换寄存器 a(参见例如 Reverse a AVX register containing doubles using a single AVX intrinsic)。我唯一的问题是那些内在函数需要立即值,即编译时值,而我需要动态执行此操作。

我发现置换内在函数对其他寄存器中包含的整数进行操作,例如 _mm256_permutevar_pd ,但它们都不会跨车道排列(例如,使用这些指令不可能首先将 a3 放在首位。使用这些指令执行我想要的操作的唯一方法是使用 if,我宁愿避免这种情况。

我是否应该根据 if 条件对 128 位 channel 进行排列,然后在 channel 内进行动态排列?或者有更好的解决方案吗?我对性能和可维护性都感兴趣。我最多可以使用 AVX2 指令。汇编是一种选择,但我更喜欢内部函数。

最佳答案

理想情况下,在将 [ z y x w ] 打包到 vector 中之后,您可以使用 SIMD 操作执行 + 表示的任何操作。但如果不是:

以正常方式将所有 4 个元素提取为标量 double,然后做任何你想做的事:

void unpack_256_to_scalar(__m256d a) {
// unpack to two 128b halves
__m128d a01 = _mm256_castpd256_pd128(a); // extractf128_pd(a, 0) should also compile the same way, if you like more-consistent C instead of code that matches the asm you expect
__m128d a23 = _mm256_extractf128_pd(a, 1);

// and then halves of each 128b vector
double a0 = _mm_cvtsd_f64(a01);
double a1 = _mm_cvtsd_f64(_mm_unpackhi_pd(a01,a01));
double a2 = _mm_cvtsd_f64(a23);
double a3 = _mm_cvtsd_f64(_mm_unpackhi_pd(a23,a23));
...
// use the results
}

compiles (on the Godbolt compiler explorer)对于 clang 只有三个指令,或者对于 gcc 只有 4 个指令,因为它在寄存器分配方面很愚蠢:

unpack_256_to_scalar(double __vector(4)):
vextractf128 xmm1, ymm0, 0x1
vunpckhpd xmm2, xmm0, xmm0
vmovapd xmm3, xmm1 # gcc should have use vunpckhpd xmm3, xmm1,xmm1. This wasted mov is a missed-optimization bug.
vunpckhpd xmm1, xmm1, xmm1
# the empty asm statement emitted the empty string here.
vzeroupper
ret

三个指令中的每一个都产生一个不同的元素作为其 vector 结果的低位元素。不需要常量,甚至不需要立即常量(这就是为什么我选择 unpackhi_pd 而不是 shufpdvpermilpd,clang 在从其内部表示生成洗牌时使用数据移动。)

在这里使用需要 vector 作为控制掩码的变量洗牌会很疯狂。这似乎不需要任何动态/可变洗牌或提取。

顺便说一句,请参阅 标记 wiki 以获取有关编写高性能代码的一些链接。

关于c++ - 排列 AVX 寄存器的内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38453705/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com