gpt4 book ai didi

c++ - _mm_extract_epi8(...) intrinsic 以非文字整数作为参数

转载 作者:太空狗 更新时间:2023-10-29 21:47:33 27 4
gpt4 key购买 nike

我最近一直在使用 SSE 内部 int _mm_extract_epi8 (__m128i src, const int ndx),根据引用“从索引选择的压缩整数数组元素中提取整数字节” .这正是我想要的。

但是,我通过 _m128i 上的 _mm_cmpestri 确定索引,它执行具有显式长度的字符串数据的压缩比较并生成索引。该索引的范围是 0..16,其中 0..15 表示有效索引,16 表示未找到索引。现在要提取索引位置的整数,我想到了执行以下操作:

const int index = _mm_cmpestri(...);
if (index >= 0 && index < 16) {
int intAtIndex = _mm_extract_epi8(..., index);
}

这给我们留下了 gcc (-O0) 编译器错误:

错误:选择器必须是 0..15 范围内的整数常量

解决此问题的一个糟糕方法是在索引上设置一个开关,并为 0..15 范围内的每个索引调用一个 _mm_extract_epi8。我的问题是是否有我没有看到的更好/更好的方法。

更新:用-O3优化,没有编译错误;不过仍然使用 -O0。

最佳答案

只是总结并结束问题。

我们讨论了从 _m128i sse 中提取 [0..15] 中索引 i 处的字节的 3 个选项,其中 i 不能在编译时减少为文字:

1) 开关 & _mm_extract_epi8:在 i 上有一个 开关 并且 [0..15] 中的每个 i 都有一个 case 执行 _mm_extract_epi8(sse ,i);像 i 现在一样工作是编译时文字。

2) Union hack: 有一个 union SSE128i { __m128i sse;字符[16]数组; },将其初始化为 SSE128i sse = { _mm_loadu_si128(...) } 并使用 sse.array[i] 访问索引 i 处的字节。

3) 将第i个元素打乱到位置0和_mm_extract_epi8:使用_mm_shuffle_epi8(sse,_mm_set1_epi8(i))将第i个元素打乱到位置0;使用 _mm_extract_epi8(sse,0) 提取它。

评估:我在 Intel Sandy Bridge 和 AMD Bulldozer 架构上对这三个选项进行了基准测试。转换选项以微弱优势获胜。如果有人感兴趣,我可以发布更详细的数字和基准设置。

更新:评估基准设置:解析 1GB 文件的每个字节。对于某些特殊字节,增加一个计数器。使用_mm_cmpistri 查找特殊字节的索引;然后使用提到的三种方法之一“提取”字节,并区分大小写,其中计数器递增。代码是使用 GCC 4.6 和 -std=c++0x -O3 -march=native 编译的。

对于每种方法,基准测试在 Sandy Bridge 机器上运行 25 次。结果(以秒为单位的运行时间的平均值和标准偏差):

切换和提取:平均值:1071.45标准差:2.72006

联盟黑客:平均值:1078.61标准偏差:2.87131

从位置 0 开始混洗和提取:平均值:1079.32标准偏差:2.69808

差异很小。我还没有机会查看生成的 asm。不过,看到差异可能会很有趣。现在我无法发布基准测试的完整代码,因为它包含非公开来源。如果我有时间,我会提取这些并发​​布源代码。

关于c++ - _mm_extract_epi8(...) intrinsic 以非文字整数作为参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12913451/

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