C++ C+中奇怪的运行时间+;循环

C++ C+中奇怪的运行时间+;循环,c++,loops,optimization,C++,Loops,Optimization,所以,我正在编写一个程序,其中优化是一个关键因素。然而:在优化过程中,我注意到一个我认为相对简单的函数运行时间太长。尤其是因为,相比之下,一个更难的函数正在缩短 //简单函数 int get_chunk_索引(标准::向量块,int x,int y){ glm::vec3 target=glm::vec3(x*40,0,y*40); for(int i=0;i40。它最终只是一个深度副本,因为Chunk是一个相当大的文件,我没有注意到副本 工作代码: // Simple function i

所以,我正在编写一个程序,其中优化是一个关键因素。然而:在优化过程中,我注意到一个我认为相对简单的函数运行时间太长。尤其是因为,相比之下,一个更难的函数正在缩短

//简单函数
int get_chunk_索引(标准::向量块,int x,int y){
glm::vec3 target=glm::vec3(x*40,0,y*40);
for(int i=0;i

如果你想要更多的函数,请随意询问,但这是一个相当大的程序,所以我不能在这里包括所有内容


PS:Chunk的大小只有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
//简单函数
int get_chunk_索引(std::vector&chunk,intx,inty){
glm::vec3 target=glm::vec3(x*40,0,y*40);
for(int i=0;i
一些简单的选项

1)
chunks
按值传递,这将创建所传递向量的完整副本。尝试通过
const
引用传递(即
const std::vector&chunk

2) 与其传递
x
y
,并从中创建
glm::vec3
(不管是什么-它是非标准的),不如将函数更改为通过引用接受
glm::vec3
。这将强制调用方创建对象,但也允许调用方控制对象的更新(而不是每次重新创建新对象)

3) 将
chunks.size()
的计算从循环中取出,并使用preincrement(不会创建临时)而不是post increment

std::size_t size = chunks.size();
for (int i = 0; i < size; ++i) {
    if (chunks[i].trans.GetPos() == target)
    {
        return i;
    }
}
5) 与其传递向量,不如传递其
开始
结束
迭代器。这将使循环更加简化

6) 检查被调用的
getPos()
函数正在做什么,并对其进行优化


7) 在打开优化的情况下进行计时测量,并在大量函数调用中进行测量。单个函数调用的性能度量在实践中意义不大(影响性能的其他方面的抖动将主导您的度量)。

尝试将
chunks.size()
从循环中取出,将其分配给一个变量。那么
getPos()
有什么作用呢?您是否尝试过将
std::vector
更改为
const std::vector&
?允许删除深度副本可以节省一点时间。链接到pastebin的风格很差,因为它不受此网站的控制,您或pastebin本身可能会决定稍后删除它。发布一个可以重现您描述的问题的独立示例[在此过程中,您可能会发现您解决了问题],向量中事物输入的分布直接关系到函数任何实例的运行时间——因此函数的运行时间稳定性直接关系到输入数据的可能概率分布。@Barmar getpos字面上只是从转换类返回私有成员pos只是一个注记“预增量”:除了最复杂和复杂的情况外,所有现代编译器都可以优化这些临时值的生成。[我个人会按照4(b)使用C++11范围循环,但这与基本类型的“临时性”无关],是的。但对于提供重载的pre和post-increment的用户定义类型(大多数人这样做会导致这些操作符具有“正常”语义)则不一定如此这意味着一个临时变量来保存post increment的前一个值——编译器不一定能够省略它,除非它在调用站点上能够看到重载运算符的定义。尽管向量的迭代器可以是(实际上通常是)指针,但没有什么可以阻止它们成为具有重载运算符的用户定义类型。
std::size_t size = chunks.size();
for (int i = 0; i < size; ++i) {
    if (chunks[i].trans.GetPos() == target)
    {
        return i;
    }
}
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);
for (const auto &i : chunks)
{
    if (i.trans.GetPos() == target) return std::distance(chunks.begin(), i);
}