Gather/Extract 整数数组的第一位
Gather/Extract first Bit from Integer Array
问题
是否存在 gathers/extracts int[32]
的第一位并将其存储到 int
中的指令?
我知道内在的 pext
但这并不是我真正想要的。
我确实有一个代码,但我想也许有一个指定的指令。
ints
数组除第一位外为零。因此,不需要掩蔽。
代码
void ints2bits(int &bits, int *ints) {
bits = (ints[0] << 0) + (ints[1] << 1) + ... + (ints[31] << 31);
}
更新和反馈:
刚刚测试了哈罗德的建议。它工作得很好,我可以获得很好的加速。
没有一条指令甚至可以读取那么多数据,但是使用 _mm_movemask_ps
可以快速处理 4 组(AVX2 为 8 组)。忽略它声称是浮点指令的事实,它只是收集并附加 4 个最高位。
当然,使用 _mm_slli_epi32
可以很容易地将底部移动到顶部。
所以把它放在一起(未测试)
int res = 0;
for (int i = 0; i < 32; i += 4) {
__m128i x = _mm_load_si128((__m128i*)&ints[i]); // I assume it's aligned
x = _mm_slli_epi32(x, 31);
int bits = _mm_movemask_ps(_mm_castsi128_ps(x));
res += bits << i;
}
AVX2 的扩展非常明显。
另一种可能的方法是将每个车道移动一个可变数量(AVX2 之前这需要乘法),然后求和,当然首先是垂直的,最后保存水平的和。这可能会更慢,而且肯定更尴尬。
问题
是否存在 gathers/extracts int[32]
的第一位并将其存储到 int
中的指令?
我知道内在的
pext
但这并不是我真正想要的。我确实有一个代码,但我想也许有一个指定的指令。
ints
数组除第一位外为零。因此,不需要掩蔽。
代码
void ints2bits(int &bits, int *ints) {
bits = (ints[0] << 0) + (ints[1] << 1) + ... + (ints[31] << 31);
}
更新和反馈:
刚刚测试了哈罗德的建议。它工作得很好,我可以获得很好的加速。
没有一条指令甚至可以读取那么多数据,但是使用 _mm_movemask_ps
可以快速处理 4 组(AVX2 为 8 组)。忽略它声称是浮点指令的事实,它只是收集并附加 4 个最高位。
当然,使用 _mm_slli_epi32
可以很容易地将底部移动到顶部。
所以把它放在一起(未测试)
int res = 0;
for (int i = 0; i < 32; i += 4) {
__m128i x = _mm_load_si128((__m128i*)&ints[i]); // I assume it's aligned
x = _mm_slli_epi32(x, 31);
int bits = _mm_movemask_ps(_mm_castsi128_ps(x));
res += bits << i;
}
AVX2 的扩展非常明显。
另一种可能的方法是将每个车道移动一个可变数量(AVX2 之前这需要乘法),然后求和,当然首先是垂直的,最后保存水平的和。这可能会更慢,而且肯定更尴尬。