我是GCC的C矢量扩展的新手。我正在考虑在我的项目中使用它们,但它们的实用性(在某种程度上)取决于能够有效地将向量中的所有元素向左移动一个位置并将结果存储在新向量中。我怎样才能有效地做到这一点(例如以SIMD加速的方式)?
所以,基本上:
背景信息(你可以跳过这个):这种转换的目的是处理矩阵,其中每一行用向量表示。具体来说,它将使人们能够将ShiftedVector视为下方行的左上对角线,并比较一个SIMD操作中的所有值。如果有另一种方法将矢量与另一个矢量偏移一个元素进行比较,那么这也可以解决问题。但我假设没有,并且执行此比较的最有效方法是向左移动所有元素并以1:1进行比较。
一般规定:
这里的瓶颈似乎是缺乏关于使用内在函数的过程的一般信息。似乎人们使用汇编(我不是专家)或自动矢量化(doesn't work well here),因此矢量类型是最合乎逻辑的选择。
谢谢!
答案 0 :(得分: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”指令可以将它滑过...
答案 1 :(得分:0)
最快的转变根本没有转变(即没有动作,没有副本):
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.
如果算法允许(即移位数量有限并且事先已知),则可以保留足够的空间,并仅通过递增指针来“移位”。