我有以下循环。目标是在数组tmp
的所有元素之间执行操作,并将其存储在标量b
中。该操作等同于添加,因此没有特定的执行顺序。例如,如果我们有+ b + c + d,我们可以按任何顺序计算它,这意味着(a + b)+(c + d)也是可能的。这同样适用于此操作。但是,有一些特殊条件会以不同的方式导致结果。
tmp.e
和b.e
为longs
,而tmp.x
和b.x
为doubles
。
是否有任何形式可以比较所有tmp.e
,例如对SSE的2对,并相应地执行b.x
的正确计算。在所有情况下,它都可以被视为addMul,在第一种情况下,它只是乘以1,在其他情况下乘以0或BOUND。有可能对此进行矢量化吗?如果是这样,怎么样?
感谢。
void op(vec& tmp, scalar& b)
{
for (i = 1; i < n; ++i)
{
if (b.e == tmp.e[i])
{
b.x += tmp.x[i];
b.normalize();
continue;
}
else if (b.e > tmp.e[i])
{
if (b.e > tmp.e[i]+1)
{
continue;
}
b.x += tmp.x[i] * BOUND;
b.normalize();
}
else
{
if (tmp.e[i] > b.e+1)
{
b.x = tmp.x[i];
b.e = tmp.e[i];
b.normalize();
continue;
}
b.x = b.x * BOUND + tmp.x[i];
b.e = tmp.e[i];
b.normalize();
}
}
}
答案 0 :(得分:3)
SIMD代码中的每个元素条件通常通过使用压缩比较指令来处理,以生成全零和全一元素的掩码。您可以将此用于AND或OR向量。所以例如您可以通过使用AND来仅增加通过测试的元素,以生成一个向量,其中元素应该递增1,而元素不应该递增0,因为0是加法的标识值。 (x + 0 = x)。
您还可以根据蒙版计算两个结果,然后将它们混合在一起。 (使用AND和OR,或使用向量混合指令。)
这种做SIMD条件的方法就像cmov
:你必须计算分支的两边,即使你在向量中处理的所有元素都占据了分支的同一侧。
您的数据看起来已经是数组结构格式。因此,您可以根据e
值的向量对操作生成掩码,以便与x
值的向量一起使用。如果long
为32位,则可以比较4个元素,并解压低和解包高,以获得具有64位元素的两个掩码以匹配您的双精度。如果数组很小(因此它们适合缓存甚至.e[]
占用的空间与.x[]
一样多),那么长度与双精度相同意味着更少的解包。
无论如何,它看起来并不乐观。条件太多,我不知道整个事情究竟要完成什么,以及输入数据可能存在哪些限制。如果我对这个问题有更多的了解,也许我可以想出一种矢量化的方法来做一些。
哦,我认为另一个致命缺陷是每次迭代都取决于之前的迭代,因为它可能会修改b
。因此,您无法进行向量化并行执行多次迭代,除非您可以根据最后一个向量元素计算出更新b
的规则。