我目前正在使用C++中的fstream加载数据,该数据有7.1GB。txt文件如下:
item1 2.87 4.64 ...
item2 5.89 9.24 ...
... ... ... ...
这个数据表格有300000行和201列(其中1列是条目名称,200列是其权重),每个单元格都是一个双精度浮点型的数字。我现在的做法是:
ifstream click_log(R"(1.txt)", ifstream::in);
string line;
unordered_map<string, vector<double>> dict;
while (getline(click_log, line)){
istringstream record(line);
string key;
vector<double> weights;
double weight;
record >> key;
while (record >> weight){
weights.push_back(weight);
}
dict[key] = weights;
}
然而,我的电脑(AMD 3700X,8个核心)需要大约30分钟才能完全加载文件。 这是因为复杂度O(m*n)太慢了,还是因为将字符串转换为双精度浮点数太慢了呢? 从.txt加载数据的最有效方法是什么?
std::array
,这样可以减少由于std::vector
机制而导致的大量释放/重新分配/复制。然后,您应该直接将内容写入目标容器,而不是使用临时向量(并进行许多额外的拷贝)。但我有一个问题,您的文件中是否也包含 "+-----+"?还是您为了可读性而添加的?因为您的代码似乎没有处理它们,这很令人困惑。 - Fareanorweights.reserve(200)
将是一个显著的改进。这将有额外的好处,即向量不会过大。其次,使用移动语义将其添加到映射中将有助于防止额外的复制。最后,在您的unordered_map
上保留足够的桶将有助于避免重新哈希,这也是昂贵的。如果您不确定,请考虑使用std::map
作为替代方案。 - paddydouble
值也是一个不可忽视的成本。如果您知道您的数据始终符合特定格式(例如始终使用十进制表示法),则可以考虑编写自己简化的double
值解析器,如果在进行这些其他优化后性能分析显示它具有重要意义。如果您可以使用float
而不是double
(假设您不需要高精度),这将几乎减半您的内存占用。 - paddydict[key] = weights;
- 这一行是一个复制赋值。直接将内容写入dict[key]
或者至少进行移动或使用std::vector::swap
- 直接填充更好。 - Aziuth