考虑到干净代码的性能,啥更好

Posted

技术标签:

【中文标题】考虑到干净代码的性能,啥更好【英文标题】:Performance with clean code in mind, what is better考虑到干净代码的性能,什么更好 【发布时间】:2017-04-25 09:37:23 【问题描述】:

对于 for 循环的简洁性,我喜欢基于范围的 for 循环。在 for 循环中,我想填充一个我事先知道其大小的向量,但我缺少一个索引值。我现在有两种方法,声明一个向量并使用 push_back 添加元素或创建一个初始化向量(应该更快,因为不需要分配?),计算索引并插入一个元素。

问题:其中一个的性能缺点是什么和/或有更好的实现。

在此示例代码下方,实际代码包含的项目数量相对较少(大概少于 10 个),但它会在此过程中运行数百万次。

    //The vector as input for the for loop
    std::vector<double> vecIn =  1, 2, 3, 4, 5 ;

    //Adding values to vectors, vector size changes on each loop right?
    std::vector<double> vecOut1;
    //Loop through vector with range looping
    for (auto& val : vecIn) 
        vecOut1.push_back(val); //In reality val is some calculated value based on the input.
    

    //Adding values to initialized vector, but need to calculate index.
    std::vector<double> vecOut2(vecIn.size());
    //Loop through vector with range looping
    for (auto& val : vecIn) 
        auto i = &val - &vecIn[0];
        vecOut2[i] = val;  //In reality val is some calculated value based on the input.
    

我喜欢第一个循环的简短性,但担心性能方面会更糟。

当然,我也可以在循环的开头声明一个索引并对其进行迭代,但这似乎有点违背清洁的目的。

编辑:为了澄清,这是我将一个向量复制到另一个向量的演示代码。在实际程序中,处理输入向量并根据输入向量计算新值。新值需要插入/附加到向量输出。在实际代码中,输入甚至不是向量,而是 boost::ublas::matrix。

【问题讨论】:

剖析一下看看:) 使用vector.reserve 如果你想复制整个向量,你可以做std::vector&lt;double&gt; vecOut1 = vecIn;,图书馆会为你做所有的工作。包括预先分配足够的空间。 这是示例代码,当然我想做的不仅仅是将一个向量复制到另一个向量中。 添加真实示例,而不仅仅是部分 【参考方案1】:

其实差不多。

你可以让编译器为你优化:

std::vector<double> vecOut1(vecIn.begin(), vecIn.end());

std::vector<double> vecOut1 = vecIn

通过这样做,您将 vecIn 复制到 vecOut1。

另外一个忠告:在for循环中能否告诉你正在处理的类型,避免使用关键字auto,并指定类型。

编辑:由于 OP 问题不清楚,这里有一个新答案。

您的第一个方法很好。也有一些不错的选择。

如果您在插入元素之前知道 vecOut2 向量的大小,则可以更好地进行索引访问:

std::vector<double> vecOut2(vecIn.size());
for(int i = 0;i < vecOut2.size(); i++)
   vecOut2[i] = vecIn[i] + /* Your calculation */;

这实际上取决于您要如何执行计算,以及计算是否是线性的(是否必须在索引之间跳转)。

【讨论】:

我编辑了我的问题,更清楚地表明我不想进行矢量复制,但提供的代码是示例代码。 我编辑了我的答案,但仍不清楚您希望如何执行您的操作以及您的计算有多复杂。 我不同意不使用自动。将迭代器的整个类型写入复杂的数据结构是耗时的,不会使您的代码更具可读性,并且如果您更改底层数据结构,则需要重写 @EyalK。你说的对。我没有说永远“停止”使用 auto 。我认为本文描述了汽车的最佳和最差acodersjourney.com/2016/02/c-11-auto【参考方案2】:

您的第一个循环需要.reserve() 以与第二个循环具有相同的性能数量级:

std::vector<double> vecOut1;
vecOut1.reserve(vecIn.size());
for (auto& val : vecIn) 
    vecOut1.push_back(val); 

reserve 预分配请求的元素而不更改向量 size- 因此循环中不会进行重新分配。

【讨论】:

以上是关于考虑到干净代码的性能,啥更好的主要内容,如果未能解决你的问题,请参考以下文章

有没有更好(更干净)的方法来使用三元运算符(不重复代码)编写这个 JS 代码?

有啥软件可以为我总结源代码吗? [关闭]

“干净”的代码,贼差的性能

有没有更好、更干净的方法来编写这个本地存储数据

SQL 性能 - 更好地插入和引发异常或检查是不是存在?

在性能方面有啥更好的?类型[,] 还是类型[][]?