12

我正在研究应该实时运行的流体动力学 Navier-Stokes 求解器。因此,性能很重要。

现在,我正在研究许多紧密循环,每个循环都占执行时间的很大一部分:没有单一的瓶颈。这些循环中的大多数都执行一些浮点运算,但中间有很多分支。

浮点运算主要限于加法、减法、乘法、除法和比较。所有这些都是使用 32 位浮点数完成的。我的目标平台是至少带有 SSE1 指令的 x86。(我在汇编器输出中验证了编译器确实生成了 SSE 指令。)

我正在使用的大多数浮点值都有一个相当小的上限,接近零值的精度并不是很重要。所以我想到了:也许切换到定点算术可以加快速度?我知道真正确定的唯一方法是衡量它,这可能需要几天时间,所以我想事先知道成功的几率。

定点在 Doom 时代风靡一时,但我不确定它在 2010 年的表现如何。考虑到现在有多少硅投入到浮点性能中,定点算法是否仍有机会给我一个显着的速度提升?有没有人有任何可能适用于我的情况的实际经验?

4

3 回答 3

6

坚持使用浮点数。只有当您可以在 8 位或 16 位内工作并使用 SIMD 时,定点才真正有用(图像处理和音频是典型的用例)。

现代 CPU 通常有 2 个 FPU,每个时钟周期最多可以发出 2 个 FP 指令。然后,您还可以使用 4 路 FP SIMD (SSE) 进行优化。

如果您仍在努力获得良好的性能,请尝试使用更好的编译器,例如 Intel 的 ICC。此外,由于 64 位模型中寄存器数量的增加,64 位 Intel 可执行文件往往比其 32 位可执行文件要快一些,因此请尽可能构建 64 位。

当然,你也应该分析你的代码,这样你就可以确定热点在哪里。你没有说你正在使用什么操作系统,但Windows上的VTune 、 Linux上的Zoom或 Mac OS X 上的Shark都可以帮助你快速轻松地找到性能瓶颈。

于 2010-04-19T12:48:28.487 回答
3

正如其他人所说,如果您已经在使用浮点 SIMD,我怀疑您会在定点方面获得很大改进。

您说编译器正在发出 SSE 指令,但听起来您并没有尝试编写矢量化 SSE 代码。我不知道编译器通常在这方面有多好,但这是需要调查的。

另外两个值得关注的领域是:

  1. 内存访问——如果你所有的计算都是在 SSE 中完成的,那么缓存未命中可能会比实际数学花费更多的时间。

    1. 您可以使用例如 _mm_prefetch 或 __builtin_prefetch 预取数据(取决于您的编译器/平台)。
    2. 检查输入和输出之间的混叠功能;这些可能导致额外的内存读取/写入。
    3. 考虑以不同的方式存储您的数据 - 如果您的 x 坐标的流体求解器求解器独立于 y 坐标,则将它们存储在不同的数组中可能对缓存更友好。如果它们一起解决,请考虑交错(例如 xyx y...)
  2. 展开- 您应该能够从展开内部循环中获得性能优势。目标不是(正如许多人所认为的)减少循环终止检查的数量。主要好处是允许独立指令交错,隐藏指令延迟。这里有一个名为VMX 优化的演示文稿:将其提升一个级别,这可能会有所帮助;它专注于 Xbox360 上的 Altivec 指令,但一些展开的建议也可能对 SSE 有所帮助。

正如其他人提到的那样,个人资料,个人资料,个人资料。然后让我们知道什么仍然很慢:)

PS - on one of your other posts here, I convinced you to use SOR instead of Gauss-Seidel in your matrix solver. Now that I think about it, is there a reason that you're not using a tri-diagonal solver?

于 2010-04-19T21:40:10.390 回答
0

您的机器针对浮点进行了很好的优化,因此使用定点分数可能不会节省太多。

你说没有一个瓶颈,但可能有多个,如果你设法刮掉其中任何一个,那么其余的将占用更大比例的剩余时间,引起你的注意,所以你也可以刮掉它们。

您可能已经这样做了,但我会确保不仅耗时的函数尽可能快,而且它们被调用的次数不过是必要的。

于 2010-04-19T17:01:08.837 回答