在构造函数中,我有一段代码,它执行以下操作:
代码片段1
for (unsigned i=0; i<n; ++i) {
auto xIdIt = _originIdSet.find(xIds[i]);
auto yIdIt = _originIdSet.find(yIds[i]);
if (xIdIt == _originIdSet.end()) { _originIdSet.insert(xIds[i]); }
if (yIdIt == _originIdSet.end()) { _originIdSet.insert(yIds[i]); }
}_originIdSet是std::unordered_set<uint32_t>类型的
xIds和yIds是std::vector<uint32_t>类型的
xIds和yIds包含很多重复的条目。
xIds = {1,2,1,2,3,5,....} yIds = {2,3,4,1,4,1,....}
xIds[i]绝不等于yIds[i]
我正在用gcc 5.30编写如下:g++ -g -Wall -m64 -O3 -std=c++11
我一直在分析这段代码(即代码片段1)在n = 10k^2时所花费的时间,我发现如果我将代码更改为:
代码片段2
for (unsigned i=0; i<n; ++i) {
// We cannot insert duplicates in a set so why check anyway
_originIdSet.insert(xIds[i]);
_originIdSet.insert(yIds[i]);
}它将慢大约5秒(总运行代码片段1需要大约15秒)。
我想知道性能下降的根本原因是什么。我的第一个猜测是,这是由适当的分支优化(出色的解释here)引起的,但是我认为,在这种情况下,只在使用if/else条件时才会应用分支优化是没有意义的。希望有人能澄清这里发生了什么。
发布于 2017-08-03 11:55:31
以下是两个样本:
#include <unordered_set>
#include <vector>
#include <chrono>
#include <iostream>
using namespace std;
int main() {
unsigned n = 10000000;
unordered_set<uint32_t> _originIdSet;
vector<uint32_t> xIds, yIds;
for (unsigned i = 0; i < n; ++i) {
xIds.push_back(rand() % n);
yIds.push_back(rand() % n);
}
auto start = chrono::steady_clock::now();
for (unsigned i = 0; i < n; ++i) {
auto xIdIt = _originIdSet.find(xIds[i]);
auto yIdIt = _originIdSet.find(yIds[i]);
if (xIdIt == _originIdSet.end()) { _originIdSet.insert(xIds[i]); }
if (yIdIt == _originIdSet.end()) { _originIdSet.insert(yIds[i]); }
}
auto end = chrono::steady_clock::now();
std::cout << "inserted " << _originIdSet.size() << " to " << chrono::duration_cast<chrono::milliseconds>(end-start).count() << " milliseconds" << std::endl;
}不经任何检查:
for (unsigned i = 0; i < n; ++i) {
_originIdSet.insert(xIds[i]);
_originIdSet.insert(yIds[i]);
}我看到了3200 vs和3400 vs时差的5%。
但是,如果我将两个数组xIds & yIds替换为一个包含来自两个数组的所有元素的数组,那么对于这两种情况,我得到相同的时间,它的工作速度比两个数组慢。
我认为,这是因为方法find()不抛出任何异常,而且它是常量的。现代的cpu能够对每个线程执行一次以上的指令,而不是明显地并行运行两个find()。
或者,第二种可能性,gcc能够生成SSE代码,用于计算2个哈希值,并在同一时刻为find()的两个调用搜索2位置。
https://stackoverflow.com/questions/45481248
复制相似问题