GCC C向量扩展:如何将向量的内容向左移动一个元素?

我是GCC的C矢量扩展的新手。 我正在考虑在我的项目中使用它们,但它们的实用性(在某种程度上)取决于能够有效地将向量中的所有元素向左移动一个位置并将结果存储在新向量中。 如何有效地完成这项工作(例如以SIMD加速方式)?

所以,基本上:

  • OriginalVector = {1,2,3,4,5,6,7,8}
  • ShiftedVector = {2,3,4,5,6,7,8,X}(其中X可以是任何东西。)

背景信息(你可以跳过这个):这种转换的目的是处理矩阵,其中每一行用向量表示。 具体来说,它可以使ShiftedVector视为下方行的左上对角线,并比较一个SIMD操作中的所有值。 如果有另一种方法将矢量与另一个矢量偏移一个元素进行比较,那么这也可以解决问题。 但我假设没有,并且执行此比较的最有效方法是向左移动所有元素并以1:1进行比较。

一般规定:

  • 在此过程中不得损害原始载体
  • 如果我必须使用某种类型的x86内部函数 ,这很好,但我不知道是哪种或如何
  • 如果我丢失了向量中最左边的元素并且在最右边引入了乱码,这很好
  • 如果最有效的方法是从第二个位置到结束+ 1的原始矢量的未对齐加载,那很好,但我仍然想知道如何最好地编码这个

这里的瓶颈似乎是缺乏关于使用内在函数的过程的一般信息。 似乎人们使用汇编(我不是专家)或自动矢量化( 这里不能很好地工作 ),因此矢量类型是最合乎逻辑的选择。

谢谢!

在手册的深处爬行,我发现了这一点愚蠢:

typedef int v8si __attribute__ ((vector_size (32))); v8si OriginalVector, masker, ShiftedVector; OriginalVector = {1, 2, 3, 4, 5, 6, 7, 8}; masker = {1,2,3,4,5,6,7,0}; ShiftedVector = __builtin_shuffle(OriginalVector, masker); 

我在“masker”的末尾无理由地放置0(任何元素0-7都可以工作)。 这样做只是将原始元素映射到masker中定义的位置,并将它们保存到结果中。

但是虽然这是一个答案,但它可能不是“最佳”答案,因为我认为有一种比创建新向量更好的方法,使用新向量占用寄存器,分配位置,使每个元素不合适并且把它放在另一个任意的地方,并保存结果。

是的,我们可以将循环器之外的掩蔽器缓存,而不是每次都创建它,但我想有一些简单的“permute left”指令可以将它滑过…

最快的转变根本没有转变(即没有移动,没有复制):

 int Data[16] = { 1, 2, 3, 4, 5, 6, 7, 8, 0, 0, 0, 0, 0, 0, 0, 0, }; int* Ptr = Data; // first shift Ptr++; // second shift Ptr++; // and so on. 

如果算法允许(即,移位的数量是有限的并且事先已知),则可以保留足够的空间,并且仅通过递增指针来“移位”。