【发布时间】:2011-09-10 08:51:17
【问题描述】:
我正在尝试使用 SIMD 内在函数编写流压缩(获取一个数组并删除空元素)。循环的每次迭代一次处理 8 个元素(SIMD 宽度)。
使用 SSE 内在函数,我可以使用 _mm_shuffle_epi8() 相当有效地做到这一点,它执行 16 个条目的表查找(收集并行计算术语)。随机索引是预先计算的,并使用位掩码进行查找。
for (i = 0; i < n; i += 8)
{
v8n_Data = _mm_load_si128(&data[i]);
mask = _mm_movemask_epi8(&is_valid[i]) & 0xff; // is_valid is byte array
v8n_Compacted = _mm_shuffle_epi8(v16n_ShuffleIndices[mask]);
_mm_storeu_si128(&compacted[count], v8n_Compacted);
count += bitCount[mask];
}
我现在的问题是我也想为 Altivec SIMD 实现此功能(不要问为什么 - 错误的商业决策)。 Altivec 没有关键成分 _mm_movemask_epi8() 的等效项。所以,我需要找到一种方法来
emulate _mm_movemask_epi8() - 似乎很昂贵,需要几个班次和 ORs
直接高效生成随机索引 -
即索引 i 将是未压缩数据中第 i 个有效元素的索引
element_valid: 0 0 1 0 1 0 0 1 0
gather_indices: x x x x x x 6 4 1
scatter_indices: 3 3 2 2 1 1 1 0 0
串行执行此操作很简单,但我需要并行执行 (SIMD)。生成带有前缀总和的分散索引似乎很容易,但由于 AltiVec 和 SSE 都没有分散指令,所以我需要收集索引。收集索引是分散索引的反函数,但是如何并行得到呢?我知道在 GPU 编程的开创性时代,converting scatters to gathers 是一种常用技术,但所描述的这两种方法似乎都不实用。
也许如果不坚持压缩保留元素顺序将允许更有效的实施?我可以放弃。
【问题讨论】:
标签: sse simd vectorization altivec stream-compaction