C++ 元件部分移位是否有simd指令/固有/内置?

C++ 元件部分移位是否有simd指令/固有/内置?,c++,gcc,x86,sse,simd,C++,Gcc,X86,Sse,Simd,一个最简单的例子会更有益: 假设我有一个排序的8个整数={10,20,30,40,50,60,70,80}我的用例是用于排序的整数,但是考虑到向量指令作用于整个数据集,我不确定这些信息是否有价值 需要的操作很少: 插入并移动。 ->在其排序位置插入25。 ->变为索引2处的insert 25,并移动rest 10,20,30,40,50,60,70,80变成:10,20,25,30,40,50,60,70 拆下、移动并插入后部。 ->从阵列中移除20,如果发现并移除了20,则在背面插入90。 1

一个最简单的例子会更有益:

假设我有一个排序的8个整数={10,20,30,40,50,60,70,80}我的用例是用于排序的整数,但是考虑到向量指令作用于整个数据集,我不确定这些信息是否有价值

需要的操作很少:

插入并移动。 ->在其排序位置插入25。 ->变为索引2处的insert 25,并移动rest

10,20,30,40,50,60,70,80变成:10,20,25,30,40,50,60,70

拆下、移动并插入后部。 ->从阵列中移除20,如果发现并移除了20,则在背面插入90。 10,20,30,40,50,60,70,80变成10,30,40,50,60,70,80,90

或者一套指令能让它工作吗


我正在尝试使用降序排序数组的多步骤插入和移位部分

做你想做的事情的一个通用方法是[u]int_{8,16,32,64}或甚至float/double的基本思想是相同的:

在输入中插入x:

从输入中删除不小于x的第一个元素:

如果要删除的元素数量不能保证为1,即它可能不存在或存在多次,这就更加困难,因为每个输出值都可能取决于每个输入值。一个想法可能是使用maskmove和popcount比较相等性并计算元素的数量

对于换档,您可以使用

SSE2和仅一个128位寄存器:, SSSE3和128位寄存器序列: AVX2和一个256bit寄存器:对于预先确定的索引向量,没有AVX2等效于先前的指令,可以在整个256bit寄存器上工作 如果您的输入存储在内存中,请使用一个元素偏移量再次加载它。这需要在数组的每一端之外有一个安全的元素—如果您多次执行这些操作,则可能会引入显著的写-读延迟 对于广播,我建议只使用_-mm[256]_-set1_-epi32内在函数,让编译器找出没有AVX2最有效的方法,这可能需要一次洗牌

根据SSE/AVX版本,存在各种尺寸/类型的最小/最大运算符-只需搜索以pmin/pmax开头的指令

据我所知,AVX512之前没有无符号比较,但是如果没有值大于最大有符号值,当然可以使用有符号比较。或者,您可以在比较之前翻转上一位来解决这个问题,我假设在stackoverflow上有一个相关的问题


最后,如果您有SSE4.1,混合是通过以下步骤完成的。否则,您需要执行一些按位and/andnot/or操作。

AVX2 vpermd用于256位向量,SSE2 pshufd用于128位dword元素向量,这可能会移动其他元素以设置vpblendd以插入一个。不过,并没有什么特别有效的方法,也并没有什么好方法可以将插入位置转换为洗牌控制向量。;如果您试图构建SIMD排序,那么SIMD向量中的插入排序是不好的?您是否将其中8个存储在两个SSE寄存器中?还是使用int16?还有:签名还是未签名?或者你们有AVX2吗?如何根据值或索引确定要删除的对象?如果由值决定,如果元素不存在,会发生什么?如果在删除后的末尾插入零,数组将不再排序。Int32。目前我没有直接处理SSE寄存器,主要是通过OpenMP工作。>还有:签名还是未签名?无论哪种方法有效,值本质上都是无符号的。>或者你们有AVX2吗?我知道。>如何通过值或索引确定要删除的对象?按排序数组上的值搜索。正如我所说,需要从示例中的数组中删除20个。>如果由值决定,如果元素不存在,会发生什么?没有什么数组保持原样。数组是否实际存储在内存中?这将简化移位,只需从偏移地址加载即可。如果要删除的号码存在多次,会发生什么情况?另外,什么也不做,如果元素不存在,这会稍微复杂一点-我会有一个相对简单的解决方案,删除不小于x的第一个元素或不大于x的最后一个元素-这是等效的,如果x正好存在,那么sesimd向量不能有效地支持您要求的操作类型;你到底想解决什么问题?您可能应该以不同的方式处理高级问题。
// Shift your input array (e.g. "abcefghi") to the right:
out = ShiftRight(input); // out = 0abcefgh
// broadcast the to-be-inserted element (e.g., 'd')
insert = broadcast(x); // insert = dddddddd
// compute 
out = min(max(out,insert),input)
//  == min(max(0abcefgh,dddddddd),abcefghi)
//  == min(ddddefgh,abcefghi) == abcdefgh
// shift input (e.g., "abcdefgh") to the left (insert something at the end)
out = ShiftLeft(input); // out = bcdefghX
// determine elements smaller than `x` (e.g., "f") by broadcast and compare
mask = broadcast(x) < input; // mask = 11111000
// take masked elements from `input` and other values from `out` (using a blend instruction)
out = blend(mask, input, out); // == abcdeghX