6

与我的另一个问题相关,我现在修改了稀疏矩阵求解器以使用 SOR(连续过度松弛)方法。现在的代码如下:

void SORSolver::step() {
    float const omega = 1.0f;
    float const
        *b = &d_b(1, 1),
        *w = &d_w(1, 1), *e = &d_e(1, 1), *s = &d_s(1, 1), *n = &d_n(1, 1),
        *xw = &d_x(0, 1), *xe = &d_x(2, 1), *xs = &d_x(1, 0), *xn = &d_x(1, 2);
    float *xc = &d_x(1, 1);
    for (size_t y = 1; y < d_ny - 1; ++y) {
        for (size_t x = 1; x < d_nx - 1; ++x) {
            float diff = *b
                - *xc
                - *e * *xe
                - *s * *xs - *n * *xn
                - *w * *xw;
            *xc += omega * diff;
            ++b;
            ++w; ++e; ++s; ++n;
            ++xw; ++xe; ++xs; ++xn;
            ++xc;
        }
        b += 2;
        w += 2; e += 2; s += 2; n += 2;
        xw += 2; xe += 2; xs += 2; xn += 2;
        xc += 2;
    }
}

现在奇怪的是:如果我增加omega(松弛因子),执行速度开始显着依赖于各种数组中的值!

对于omega = 1.0f,执行时间或多或少是恒定的。对于omega = 1.8,第一次执行这 10 次通常需要 5 毫秒step(),但在模拟过程中这将逐渐增加到接近 100 毫秒。如果我设置omega = 1.0001f,我会看到执行时间相应地略有增加;越高omega,模拟过程中的执行时间就越快。

由于所有这些都嵌入在流体求解器中,因此很难提出一个独立的示例。但是我已经保存了初始状态并在每个时间步重新运行该状态的求解器,以及求解实际时间步。对于初始状态,它很快,对于随后的时间步长,它逐渐变慢。由于其他条件相同,这就证明了这段代码的执行速度取决于这六个数组中的值。

这在使用 g++ 的 Ubuntu 以及使用 VS2008 为 32 位编译时在 64 位 Windows 7 上是可重现的。

我听说 NaN 和 Inf 值对于浮点计算可能会更慢,但不存在 NaN 或 Inf。浮点计算的速度是否可能取决于输入数字的值?

4

2 回答 2

5

您最后一个问题的简短回答是“是” - 非规范化(非常接近于零)数字需要特殊处理并且可能会慢得多。我的猜测是,随着时间的推移,他们正在逐渐进入模拟。请参阅此相关 SO 帖子:浮点数学执行时间

将浮点控件设置为将非规范化刷新为零应该可以处理对模拟质量的影响可以忽略不计的事情。

于 2010-03-06T15:46:58.860 回答
0

celion 的答案被证明是正确的。他链接到的帖子说打开非规范化值的清零:

#include <float.h>
_controlfp(_MCW_DN, _DN_FLUSH);

但是,这仅适用于 Windows。在 Linux 上使用 gcc,我用一些内联汇编做了同样的事情:

int mxcsr;
__asm__("stmxcsr %0" : "=m"(mxcsr) : :);
mxcsr |= (1 << 15); // set bit 15: flush-to-zero mode
__asm__("ldmxcsr %0" : : "m"(mxcsr) :);

这是我的第一个 x86 程序集,所以它可能会被改进。但它对我有用。

于 2010-03-07T11:33:04.897 回答