Optimization 使用SSE优化有限差分

Optimization 使用SSE优化有限差分,optimization,simd,nested-loops,Optimization,Simd,Nested Loops,我想知道是否可以使用SSE(1,2,3,4…)优化以下循环: // u and v are allocated through new double[size*size] for (int j = l; j < size-1; ++j) { for (int k = 1; k < size-1; ++k) { v[j*size + k] = (u[j*size + k-1] + u[j*size + k+1]

我想知道是否可以使用SSE(1,2,3,4…)优化以下循环:

// u and v are allocated through new double[size*size]
for (int j = l; j < size-1; ++j)
{
    for (int k = 1; k < size-1; ++k)
    {
        v[j*size + k] = (u[j*size + k-1] + u[j*size + k+1] 
                       + u[(j-1)*size + k]+ u[(j+1)*size + k]) / 4.0;
    }
}
//u和v通过新的双精度[size*size]分配
对于(int j=l;j
[j*size+k]
习惯用法用于将内存块视为多维数组

遗憾的是,GCC(4.5)的
-ftree vectorize
标志不认为循环适合SIMD类型优化。(尽管我说我从来没有见过
-ftree vectorize
优化过任何东西,但最微不足道的循环除外。)


虽然我知道还有许多其他方法可以提高循环的性能(OpenMP、展开、就地算法等),但我特别想知道是否可以使用SIMD。我可能更感兴趣的是如何(如果有的话)转换这样一个循环的总体轮廓,而不是具体的实现。

看起来应该是可能的,但是因为(a)使用了双精度,(b)相对于I/O,您所做的计算非常少,(c)大多数现代x86-64 CPU都有两个FPU,那么,您的SIMD编码投资可能不会获得太多回报。

您是否尝试过
-ftree vectorizer verbose=n
?gcc会给你一些提示,说明为什么它会/没有矢量化。需要注意的一点是,如果没有
restrict
关键字,它会假设v可以别名u,这会阻塞很多SSE(在这种情况下,它最多会生成两个版本,并在运行时决定)@Ben Jackson-yes,我使用-verbose选项得出结论,它不是在向量化我的代码。我确实玩弄了
restrict
(实际上,我是C++的时候玩弄了
\uuu restrict\uuuu
),但它没有什么区别,因为GCC是内联的(并且确定
u
v
没有重叠)。我使用双倍是出于习惯。我不确定它是否是I/O绑定的,因为在我的双核共享L2系统上,使用OpenMP时,我的速度几乎是线性的。@Freddie:I/O绑定的注释是关于上面的标量循环-对于4个加载+1个存储,您只有3个FP加法和1个FP乘法-执行时间很可能由加载和存储的延迟决定,因此,加快计算速度(例如通过SIMD)可能不会给您带来任何好处。@Freddie:如果您的算法可以使用浮点而不是双精度,而没有任何数值精度或稳定性问题,那么在这种情况下,可能值得考虑SIMD(尽管请注意上述注释中的“重新计算v加载/存储”中的警告)。