Hug*_*ira 5 c++ performance simd vectorization
我正在尝试优化以下简单算法,针对 x86-64 和 arm64 中的 SIMD 指令。给定一个T位向量,以及两个Aidx与Bidx大小相同的向量T,包含 中值的索引T,函数将T'使用以下算法生成新的:
A = T[Aidx]
B = T[Bidx]
T' = A NAND B
Run Code Online (Sandbox Code Playgroud)
这是一个 C++ 实现:
#include <cstddef>
#define align 128
#define vsize 1024
struct alignas(align) vec_friendly_idx {
const static std::size_t size = vsize;
unsigned short v[size];
};
struct alignas(align) vec_friendly_bool {
const static std::size_t size = vsize;
unsigned char v[size];
};
void vecadd3(vec_friendly_bool& __restrict t, const vec_friendly_idx& aidx, const vec_friendly_idx& bidx, vec_friendly_bool& __restrict a, vec_friendly_bool& __restrict b) {
for (std::size_t i = 0; i != vec_friendly_idx::size; i++) {
a.v[i] = t.v[aidx.v[i]];
b.v[i] = t.v[bidx.v[i]];
}
for (std::size_t i = 0; i != vec_friendly_idx::size; i++) {
t.v[i] = !(a.v[i] & b.v[i]);
}
}
Run Code Online (Sandbox Code Playgroud)
GCC 生成以下 arm64 代码:
mov x5, 0
.L2:
ldrh w7, [x1, x5, lsl 1]
ldrh w6, [x2, x5, lsl 1]
ldrb w7, [x0, w7, sxtw]
ldrb w6, [x0, w6, sxtw]
strb w7, [x3, x5]
strb w6, [x4, x5]
add x5, x5, 1
cmp x5, 1024
bne .L2
movi v2.16b, 0x1
mov x1, 0
.L3:
ldr q0, [x4, x1]
ldr q1, [x3, x1]
and v0.16b, v0.16b, v1.16b
cmeq v0.16b, v0.16b, #0
and v0.16b, v2.16b, v0.16b
str q0, [x0, x1]
add x1, x1, 16
cmp x1, 1024
bne .L3
ret
Run Code Online (Sandbox Code Playgroud)
验收主要问题:
Q1. 关于如何进一步优化这个的任何想法?
理解奖励问题:
Q2。虽然 NAND 计算明显矢量化(因此仅执行 64 次迭代),但矢量索引却不是(执行 1024 次迭代)。我的印象是收集-收集指令在这里会很有帮助;但也许我错了?
Q3。我还考虑过将这些位打包起来T可以让 NAND 更快(现在,7 位是垃圾),但我有一种感觉,必要的打包/解包开销不会导致更快的执行?
| 归档时间: |
|
| 查看次数: |
160 次 |
| 最近记录: |