_mm_extract_epi8(...)内在函数,它将非文字整数作为参数

时间:2012-10-16 11:13:32

标签: c++ sse intrinsics

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

但是,我通过_mm_cmpestri上的_m128i确定索引,该const int index = _mm_cmpestri(...); if (index >= 0 && index < 16) { int intAtIndex = _mm_extract_epi8(..., index); } 执行字符串数据与显式长度的打包比较并生成索引。此索引的范围是0..16,其中0..15表示有效索引,16表示未找到索引。现在要提取索引位置的整数,我想做以下几点:

switch

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

错误:选择器必须是0..15

范围内的整数常量

解决此问题的一个令人讨厌的方法是在索引上使用_mm_extract_epi8并在0..15范围内对每个索引进行{{1}}调用。我的问题是,如果有更好/更好的方式,我没有看到。

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

1 个答案:

答案 0 :(得分:2)

总结并结束这个问题。

我们讨论了从[{1}}中提取[0..15]中索引i处的字节的3个选项,其中我无法在编译时将其缩减为文字:

1)Switch&amp; _m128i sse:对{i} _mm_extract_epi8以及{0..15]中每个i switch的情况;因为我现在是一个编译时文字。

2)联盟黑客:拥有_mm_extract_epi8(sse,i),将其初始化为union SSE128i { __m128i sse; char[16] array; }并使用SSE128i sse = { _mm_loadu_si128(...) }访问索引i处的字节。

3)将第i个元素移动到位置0和sse.array[i]:使用_mm_extract_epi8将第i个元素移动到位置0;用_mm_shuffle_epi8(sse,_mm_set1_epi8(i))提取它。

评估:我对Intel Sandy Bridge和AMD Bulldozer架构的三个选项进行了基准测试。切换选项赢得了小幅度。如果有人感兴趣,我可以发布更详细的数字和基准设置。

更新:评估 基准设置:解析1GB文件的每个字节。对于某些特殊字节,请增加计数器。使用_mm_extract_epi8(sse,0)查找特殊字节的索引;然后使用上述三种方法之一“提取”字节,并进行计数器递增的大小写区分。代码是使用GCC 4.6和_mm_cmpistri编译的。

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

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

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

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

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