C:编写可自动向量化的代码,嵌套循环,GCC

4

我正在尝试编写一些可进行向量化的 C 代码。这是我尝试的循环:

for(jj=0;jj<params.nx;jj++)
    for(kk=0;kk<NSPEEDS;kk++)
        local_density_vec[jj] += tmp_cells_chunk[jj].speeds[kk];

当我使用-ftree-vectorizer-verbose=5标志运行时,GCC会给我以下消息:http://pastebin.com/RfCc04aS。如何重写它以便可以自动矢量化。 NSPEEDS为5。编辑:我已经继续研究它,但似乎无法对.speeds[kk]进行矢量化。有没有一种重新构造它的方法?

1
编译器无法将其向量化,因为它无法确定数组之间是否存在别名。此外,您的“NSPEEDS”循环次数太小,无法从向量化中获得任何加速。 - Mysticial
在这个上下文中,别名是什么意思? - superbriggs
1
别名意味着编译器不知道你的数组是否重叠。向量化通常会改变内存访问的顺序。除非能证明不会违反任何依赖关系,否则编译器无法合法地进行向量化。 - Mysticial
1
简而言之,无论你如何排列代码,它都无法进行矢量化。矢量化通常仅适用于顺序和连续的内存访问。无论您如何排序循环,这里都不是这种情况。问题在于 tmp_cells_chunk 似乎是一个结构体。这意味着您拥有 结构体数组 打包。如果要进行矢量化,可能需要切换到结构体数组的内存布局。 - Mysticial
谢谢。我会尝试更改数据类型,使其成为数组的结构体。如果我理解正确的话,这应该可以解决问题。 - superbriggs
显示剩余3条评论
1个回答

4
for (jj = 0; jj < nx; jj++) {
        partial = 0.0f;
        fp = c[jj].speeds;
        for (kk = 0; kk < M; kk++)
                partial += fp[kk];
        out[jj] = partial;
}
(...)
Calculated minimum iters for profitability: 12

36:   Profitability threshold = 11

Vectorizing loop at autovect.c:36

36: Profitability threshold is 11 loop iterations.
36: LOOP VECTORIZED.

重要提示:

1)在您的转储中,循环被认为是“复杂访问模式”(请参见日志的最后一行)。正如已经评论的那样,这与编译器无法验证别名有关。对于“简单”的访问模式,请参阅: http://gcc.gnu.org/projects/tree-ssa/vectorization.html#vectorizab

2)我的示例循环需要12次迭代才能使矢量化变得有用。由于NSPEEDS == 5,如果矢量化您的循环,编译器会浪费时间。

3)只有在我添加-funsafe-math-optimizations之后,我才能将我的循环矢量化。我相信这是由于与所得到的矢量操作具有不同的舍入或结合性行为有关。例如,请参见: http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems

4)如果你反转了循环,你可能会再次遇到“复杂”的访问模式问题。正如已经评论的那样,您可能需要反转数组组织。检查gcc矢量化文档以查看是否可以匹配其中一种模式中的跨距访问。

为了完整起见,这里是完整的示例: http://pastebin.com/CWhyqUny


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接