考虑到干净代码的性能,啥更好
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<double> 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
- 因此循环中不会进行重新分配。
【讨论】:
以上是关于考虑到干净代码的性能,啥更好的主要内容,如果未能解决你的问题,请参考以下文章