在更新所有粒子的函数中,我有以下代码:
for (int i = 0; i < _maxParticles; i++)
{
// check if active
if (_particles[i].lifeTime > 0.0f)
{
_particles[i].lifeTime -= _decayRate * deltaTime;
}
}
这会根据经过的时间减少粒子的寿命。 它会在每个循环中计算出来,所以如果我有10000个粒子,那么它不会非常高效,因为它不需要(它不会被改变)。
所以我想出了这个:
float lifeMin = _decayRate * deltaTime;
for (int i = 0; i < _maxParticles; i++)
{
// check if active
if (_particles[i].lifeTime > 0.0f)
{
_particles[i].lifeTime -= lifeMin;
}
}
这计算一次并将其设置为每个循环调用的变量,因此CPU不必每次循环计算它,理论上会提高性能。
它会比旧代码运行得更快吗?或者发布编译器是否进行了这样的优化?
我写了一个比较两种方法的程序:
#include <time.h>
#include <iostream>
const unsigned int MAX = 1000000000;
int main()
{
float deltaTime = 20;
float decayRate = 200;
float foo = 2041.234f;
unsigned int start = clock();
for (unsigned int i = 0; i < MAX; i++)
{
foo -= decayRate * deltaTime;
}
std::cout << "Method 1 took " << clock() - start << "ms\n";
start = clock();
float calced = decayRate * deltaTime;
for (unsigned int i = 0; i < MAX; i++)
{
foo -= calced;
}
std::cout << "Method 2 took " << clock() - start << "ms\n";
int n;
std::cin >> n;
return 0;
}
调试模式的结果:
Method 1 took 2470ms
Method 2 took 2410ms
结果处于发布模式:
Method 1 took 0ms
Method 2 took 0ms
但这并不奏效。我知道它并没有完全相同,但它提出了一个想法。 在调试模式下,它们大致需要相同的时间。有时方法1比方法2更快(特别是数量更少),有时方法2更快。 在释放模式下,需要0 ms。有点奇怪。
我尝试在游戏中测量它,但是没有足够的粒子来获得清晰的结果。
修改
我尝试禁用优化,并使用std::cin
让变量成为用户输入。
结果如下:
Method 1 took 2430ms
Method 2 took 2410ms
答案 0 :(得分:4)
这几乎肯定会产生什么不同,至少如果有的话 你用优化编译(当然,如果你关心的话) 性能,你正在编译优化)。最优化的 问题被称为循环不变代码运动,并且是普遍的 实施(并已经实施了大约40年)。
另一方面,可能有意义使用单独的变量 无论如何,要使代码更清晰。这取决于应用程序,但是 在许多情况下,给表达式的结果命名可以 代码更清晰。 (在其他情况下,当然,投入了很多额外的 变量可以使它不那么清晰。这一切都取决于应用程序。) 在任何情况下,对于这样的事情,尽可能清楚地编写代码 首先,然后,如果(并且仅当)存在性能问题, 个人资料,看看它在哪里,并修复它。
编辑:
非常清楚:我一般都在讨论这种代码优化。在您显示的确切情况下,由于您不使用foo
,编译器可能会完全删除它(和循环)。
答案 1 :(得分:1)
理论上,是的。但是你的循环非常简单,因此需要进行大量优化。
尝试使用-O0
选项禁用所有编译器优化。
发布运行时可能是由编译器静态计算结果引起的。
我非常有信心,任何体面的编译器都会用以下代码替换你的循环:
foo -= MAX * decayRate * deltaTime;
和
foo -= MAX * calced ;
您可以根据某种输入(例如命令行参数)设置MAX大小以避免这种情况。