C++ 循环中的奇怪 运行 次
Strange running times in C++ loops
所以,我正在编写一个程序,其中优化是一个关键因素。然而:在优化过程中,我注意到一个我认为相对简单的函数,花费的时间太长 运行。特别是相比之下,一个更困难的函数正在变得更短。
// Simple function
int get_chunk_index(std::vector<Chunk> chunks, int x, int y) {
glm::vec3 target = glm::vec3(x * 40, 0, y * 40);
for (int i = 0; i < chunks.size(); i++) {
if (chunks[i].trans.GetPos() == target) {
return i;
}
}
return -1;
}
// End simple function
如果您想要更多的功能,请随时询问,但它是一个相当大的程序,所以我不能在这里包含 所有内容。
PS:chunks 的大小永远只有 0->40。
它最终只是简单的深拷贝,因为 Chunk 是一个很大的文件,我没有注意到副本。
工作代码:
// Simple function
int get_chunk_index(std::vector<Chunk>& chunks, int x, int y) {
glm::vec3 target = glm::vec3(x * 40, 0, y * 40);
for (int i = 0; i < chunks.size(); i++) {
if (chunks[i].trans.GetPos() == target) {
return i;
}
}
return -1;
}
// End simple function
几个简单的选项。
1) chunks
正在按值传递,这会创建所传递向量的完整副本。尝试通过 const
引用(即 const std::vector<Chunk> &chunk
)代替。
2) 与其传递 x
和 y
,并从中创建一个 glm::vec3
(不管那是什么 - 它是非标准的),而是更改函数以接受 glm::vec3
参考。这会强制调用者创建对象,但也允许调用者控制对象的更新(而不是每次都重新创建一个新对象)。
3) 将 chunks.size()
的计算从循环中取出,并使用预增量(不会创建临时)而不是 post-增量。
std::size_t size = chunks.size();
for (int i = 0; i < size; ++i) {
if (chunks[i].trans.GetPos() == target)
{
return i;
}
}
4) 考虑使用迭代器而不是数组索引。
std::vector<Chunk>::const_iterator i, begin = chunks.begin(), end = chunks.end();
for (i = begin; i != end; ++i)
if (i->trans.GetPos() == target) return std::distance(begin, i);
或(C++11 及更高版本)
for (const auto &i : chunks)
{
if (i.trans.GetPos() == target) return std::distance(chunks.begin(), i);
}
5) 不传递向量,而是传递其 begin
和 end
迭代器。这样可以进一步简化循环。
6) 检查被调用的 getPos()
函数在做什么,并对其进行优化。
7) 在打开优化的情况下进行计时测量,并在函数的大量调用中进行测量。单个函数调用的性能测量在实践中意义不大(影响性能的其他因素的抖动将主导您的测量)。
所以,我正在编写一个程序,其中优化是一个关键因素。然而:在优化过程中,我注意到一个我认为相对简单的函数,花费的时间太长 运行。特别是相比之下,一个更困难的函数正在变得更短。
// Simple function
int get_chunk_index(std::vector<Chunk> chunks, int x, int y) {
glm::vec3 target = glm::vec3(x * 40, 0, y * 40);
for (int i = 0; i < chunks.size(); i++) {
if (chunks[i].trans.GetPos() == target) {
return i;
}
}
return -1;
}
// End simple function
如果您想要更多的功能,请随时询问,但它是一个相当大的程序,所以我不能在这里包含 所有内容。
PS:chunks 的大小永远只有 0->40。
它最终只是简单的深拷贝,因为 Chunk 是一个很大的文件,我没有注意到副本。
工作代码:
// Simple function
int get_chunk_index(std::vector<Chunk>& chunks, int x, int y) {
glm::vec3 target = glm::vec3(x * 40, 0, y * 40);
for (int i = 0; i < chunks.size(); i++) {
if (chunks[i].trans.GetPos() == target) {
return i;
}
}
return -1;
}
// End simple function
几个简单的选项。
1) chunks
正在按值传递,这会创建所传递向量的完整副本。尝试通过 const
引用(即 const std::vector<Chunk> &chunk
)代替。
2) 与其传递 x
和 y
,并从中创建一个 glm::vec3
(不管那是什么 - 它是非标准的),而是更改函数以接受 glm::vec3
参考。这会强制调用者创建对象,但也允许调用者控制对象的更新(而不是每次都重新创建一个新对象)。
3) 将 chunks.size()
的计算从循环中取出,并使用预增量(不会创建临时)而不是 post-增量。
std::size_t size = chunks.size();
for (int i = 0; i < size; ++i) {
if (chunks[i].trans.GetPos() == target)
{
return i;
}
}
4) 考虑使用迭代器而不是数组索引。
std::vector<Chunk>::const_iterator i, begin = chunks.begin(), end = chunks.end();
for (i = begin; i != end; ++i)
if (i->trans.GetPos() == target) return std::distance(begin, i);
或(C++11 及更高版本)
for (const auto &i : chunks)
{
if (i.trans.GetPos() == target) return std::distance(chunks.begin(), i);
}
5) 不传递向量,而是传递其 begin
和 end
迭代器。这样可以进一步简化循环。
6) 检查被调用的 getPos()
函数在做什么,并对其进行优化。
7) 在打开优化的情况下进行计时测量,并在函数的大量调用中进行测量。单个函数调用的性能测量在实践中意义不大(影响性能的其他因素的抖动将主导您的测量)。