A和B是长度为N的向量,其中N可以在20到200之间。 我想要计算这些向量之间距离的平方, 即d^2 = ||A-B||^2。
到目前为止,我有:
float* a = ...;
float* b = ...;
float d2 = 0;
for(int k = 0; k < N; ++k)
{
float d = a[k] - b[k];
d2 += d * d;
}
看起来表现良好,但是我已经对我的代码进行了分析,发现这是瓶颈(超过50%的时间都花费在这里)。
我正在使用Visual Studio 2012,在Win 7上,使用这些优化选项:/O2 /Oi /Ot /Oy-
。
我的理解是VS2012应该自动向量化该循环(使用SSE2)。
然而,如果我在代码中插入#pragma loop(no_vector)
,我并没有感受到明显的减速,所以我猜测该循环没有被向量化。编译器通过以下消息确认了这一点:
info C5002: loop not vectorized due to reason '1105'
我的问题如下:
- 是否有可能修复这段代码,以使VS2012可以将其矢量化?
- 如果不行,那么尝试自己矢量化代码是否有意义?
- 您能推荐一个网站让我学习SSE2编码吗?
- 在N的某个值以下,矢量化会适得其反吗?
- 什么是“reason '1105'”?
a
和b
。这样,您可以使用_mm_load_ps
而不是_mm_loadu_ps
。这将进一步优化代码。 - Øystein Schønning-Johansen/fp:fast
选项时才能与我的原始代码一样快。如果我指定了/fp:fast
,那么重要的是在第二个循环中加上#pragma loop(no_vector)
,以防止VS尝试对其进行矢量化并且失去第一个循环矢量化带来的一半性能提升。 - Bullfor (i = 0; i < N - 3; i += 4)
和for (i = 0; i <= N - 4; i += 4)
这两种方式之间感到犹豫——第一种方式更符合通用的 for 循环写法,而第二种方式则更容易适应不同的向量尺寸(例如,将两个 4 的出现改为 8)。 - Paul R