【发布时间】:2014-04-10 23:31:25
【问题描述】:
我有一个使用 SSE 做很多事情的函数,分析器显示我用来计算水平最小值和最大值的代码部分大部分时间都在消耗。
例如,我一直在使用以下实现:
static inline int16_t hMin(__m128i buffer) {
buffer = _mm_min_epi8(buffer, _mm_shuffle_epi8(buffer, m1));
buffer = _mm_min_epi8(buffer, _mm_shuffle_epi8(buffer, m2));
buffer = _mm_min_epi8(buffer, _mm_shuffle_epi8(buffer, m3));
buffer = _mm_min_epi8(buffer, _mm_shuffle_epi8(buffer, m4));
return ((int8_t*) ((void *) &buffer))[0];
}
如你所见,我需要计算 16 个 1 字节整数的最小值和最大值。
非常感谢任何好的建议:)
谢谢
【问题讨论】:
-
掩码
m1, m2, m3, and m4的值是多少? -
不知道有没有更好的办法。如果没有水平最大最小值运算符,您必须分四个二进制步骤进行操作(我认为您正在这样做):将 8 与 8 进行比较,然后将 4 与 4 进行比较,然后将 2 与 2 进行比较,然后将 1 与 1 进行比较。使用 int4 需要两个步骤:stackoverflow.com/questions/9877700/…
-
是的,抱歉,我忘记了随机播放控制掩码。它们被用作之前假设的 Z 玻色子
-
正如 Marat Dukhan 的回答中强调的主要原因,采用 SIMD 向量的地址不是将元素值提取到 CPU 寄存器中的正确方法,因为该样式将强制将值写入记忆。 (也不直接访问“结构”的值。)将代码更改为
_mm_cvtsi128_si32将是最好的做法。 -
可能值得一提的是,如果您的调用代码有(远)超过 16 个 1 字节整数来找到总体最小值,那么您只需累积单个 _mm_min_epi8 的结果即可更快地完成此操作操作成一个 __m128i 值,并在你的函数中执行最后一次合并结果的步骤。