使用 SIMD 内在函数对数组进行排序

问题描述

可以在 SIMD 内在对数组进行从小到大的排序。输入数组应该是这样的:

uint32_t * vector = [1968593,104757,3065928,657065,3098046,3113981,1584192,2464900];
__m256i regData;
regData = _mm256_loadu_si256( (__m256i *) (vector) );

//SORT ARRAY WITH INSTRINSICS


_mm256_storeu_si256( (__m256i) vector,regData );

//SHOW DATA SORTED
// [104757,1968593,2464900,3113981]

我正在尝试使用 __m256i 数据寄存器来解决这个问题,但我仍然找不到解决方法

我该怎么做?

PD:这是我第一次尝试 SIMD,可能我使用了错误的术语。

解决方法

是的,您可以使用批处理器偶数/奇数归并排序或任何其他排序网络。诀窍是找到适合给定 CPU 架构中可用排列数量有限的最佳网络。在这种情况下,限制因素是快速银行间置换的不可用 - 即如何找到将所有元素 0 到 7 中的元素组合在一起的通用置换,而不仅仅是来自元素 0to3 和 4to7 的元素,并且在两个银行上都发生了相同的置换。

另一种方法是使用插入排序并保持一个 simd 寄存器预先排序并一个一个地添加每个新元素。 https://stackoverflow.com/a/45480147/1716339

 shifted = shift_all_element_left_one_element(sorted);
 shifted = max(shifted,new_element_to_be_inserted__broadcast);
 sorted = min(sorted,shifted);

我已经成功地将此技术用于 XMM 寄存器中的 uint16_t 元素。但在 AVX2 中,这种技术也存在银行间置换问题,因为输入需要在银行之间转移。