【发布时间】:2015-05-19 12:09:55
【问题描述】:
(我只对前 3 个组件感兴趣)
例如:[ 1 2 3 ? ] 应该产生[ 0 0 -1 ? ]
此外,只设置一个“位”很重要,这样:[ 1 2 2 ? ] 不应产生 [ 0 -1 -1 ? ]
而是[ 0 -1 0 ? ] 或 [ 0 0 -1 ? ](不管是哪一个)
后面的(坏的)解决方案是可能的,例如通过提取水平最大值并与原始解决方案进行比较:
__m128 abcd; // input
__m128 ccac = _mm_shuffle_ps(abcd, abcd, 0x8A);
__m128 abcd_ccac = _mm_max_ps(abcd, ccac);
__m128 babb = _mm_shuffle_ps(abcd, abcd, 0x51);
__m128 abcd_ccac_babb = _mm_max_ps(abcd_ccac, babb);
__m128 mask = _mm_cmpeq_ps(abcd, abcd_ccac_babb);
也许一些按位运算来消除重复的设置位?
更新:
跟进,我已经提出了另一个(糟糕的)解决方案。
关键是将每个组件与另一个组件进行比较,避免等式(在其他地方没有 a >= b 和 b >= a)。
a > b & a >= cb > c & b >= ac > a & c >= b
屈服:
([ a b c ? ] > [ b c a ? ]) & ([ a b c ? ] >= [ c a b ? ])
在代码中:
__m128 abcd; // input
__m128 bcad = _mm_shuffle_ps(abcd, abcd, 0xC9);
__m128 gt = _mm_cmpgt_ps(abcd, bcad);
__m128 cabd = _mm_shuffle_ps(abcd, abcd, 0xD2);
__m128 ge = _mm_cmpge_ps(abcd, cabd);
__m128 mask = _mm_and_ps(gt, ge);
在[ x x x ? ] 的情况下失败(产生[ 0 0 0 ? ])。
接近:-)
有什么想法吗?
更新:
我现在正在使用以下解决方案:
__m128 abcd; // input
__m128 bcad = _mm_shuffle_ps(abcd, abcd, 0xC9);
__m128 gt = _mm_cmpgt_ps(abcd, bcad);
__m128 cabd = _mm_shuffle_ps(abcd, abcd, 0xD2);
__m128 ge = _mm_cmpge_ps(abcd, cabd);
__m128 and = _mm_and_ps(gt, ge);
__m128i bits = _mm_setr_epi32(_mm_movemask_ps(and), -1, -1, -1);
__m128i dirt = _mm_cmpeq_epi32(bits, _mm_setzero_si128());
__m128i mask = _mm_or_si128(dirt, _mm_castps_si128(and));
【问题讨论】:
-
我现在看不到任何有效或优雅的方法 - 到目前为止,我所能想到的就是使用
_mm_movemask_ps从mask中提取 4 MS 位,然后处理这将获得一个唯一的单个位值,然后您可以在需要时将其转换回掩码向量。 -
您必须按顺序执行此操作还是可以独立执行此操作,例如,如果您有一个像 {{1,2,3},{4,5,6},... } 你能独立找到 {1,2,3} 和 {4,5,6} 的最大值吗?如果您可以为不同的数字集独立执行此操作,那么使用 SIMD 会更有效。
-
@PaulR
_mm_movemask_ps作为一种按位运算的方法非常受欢迎。 -
@Zboson 不幸的是,我仅限于对同一个 SIMD 变量进行整个操作,无论与垂直操作相比效率低下
标签: c++ assembly x86 bit-manipulation sse