1

在我正在处理的程序中,我有 3 元素数组,我将其用作所有意图和目的的数学向量。

在编写代码的过程中,我很想Vector用简单的算术重载 ( +, -, * /) 来创建自己的类,这样我就可以简化如下语句:

// old:
for (int i = 0; i < 3; i++)
    r[i] = r1[i] - r2[i];

// new:
r = r1 - r2;

在生成的代码中应该或多或少相同。但是当涉及到更复杂的事情时,这真的会严重影响我的表现吗?我的代码中的一个例子是:

手写版本:

for (int j = 0; j < 3; j++)
{
    p.vel[j] = p.oldVel[j] + (p.oldAcc[j] + p.acc[j]) * dt2 + (p.oldJerk[j] - p.jerk[j]) * dt12;
    p.pos[j] = p.oldPos[j] + (p.oldVel[j] + p.vel[j]) * dt2 + (p.oldAcc[j] - p.acc[j]) * dt12;
}

使用Vector带有运算符重载的类:

p.vel = p.oldVel + (p.oldAcc + p.acc) * dt2 + (p.oldJerk - p.jerk) * dt12;
p.pos = p.oldPos + (p.oldVel + p.vel) * dt2 + (p.oldAcc - p.acc) * dt12;

我正在尝试优化我的代码以提高速度,因为这种代码在内部循环内运行。对这些事情使用重载的运算符会影响性能吗?我正在对一个由 n 个相互引力体组成的系统进行一些数值积分。这些向量操作非常常见,因此快速运行非常重要。

任何见解都会受到赞赏,我不知道的任何成语或技巧也是如此。

4

3 回答 3

2

如果您的编译器很好地内联和优化了操作,那么您通常不会看到编写好代码(使用运算符使其可读和可维护)和手动内联所有内容之间有任何区别。

手动内联也大大增加了错误的风险,因为您不会重复使用一段经过良好测试的代码,您将一遍又一遍地编写相同的代码。我建议使用运算符编写代码,然后如果你能证明你可以通过手动内联来加速它,复制代码并手动内联第二个版本。然后,您可以相互运行代码的两个变体,以证明 (a) 手动内联是有效的,以及 (b) 可读和手动内联的代码都产生相同的结果。

不过,在开始手动内联之前,有一个简单的方法可以让您自己回答问题:编写一些简单的双向测试用例,然后执行几百万次迭代,看看哪种方法执行得更快。这将教你很多关于正在发生的事情,并为你的特定实现和编译器给出一个明确的答案,你永远不会从你在这里收到的理论答案中得到。

于 2010-04-22T06:04:16.747 回答
2

我想反过来看。从 Vector 类开始,如果遇到性能问题,您可以查看手动内联计算是否更快。

除了性能之外,您还提到计算必须准确。在一个类中包含特定于向量的计算意味着更容易单独测试它们,并且使用该类的代码变得更短且更易于维护。

于 2010-04-22T06:17:35.630 回答
1

查看 ConCRT 代码示例

http://code.msdn.microsoft.com/concrtextras/Release/ProjectReleases.aspx?ReleaseId=4270

有几个(包括一个 NBody 示例)可以使用 Vector 类型和模板等执行一系列类似的技巧。

于 2010-04-29T05:12:11.483 回答