如何优化C++;将文件逐行读取到向量中? 我惊讶地发现,下面的C++只读取一个大的文件行,将这些行存储到一个向量中,输出的向量大小比Python对应的运行速度慢。如何优化它?谢谢 #include <fstream> #include <iostream> #include <vector> #include <string> int main () { std::ifstream infile("longfile.txt"); std::string line; std::vector<std::string> lines; while (std::getline(infile, line)) { lines.push_back(line); } std::cout << lines.size() << std::endl; return 0; }
Python:如何优化C++;将文件逐行读取到向量中? 我惊讶地发现,下面的C++只读取一个大的文件行,将这些行存储到一个向量中,输出的向量大小比Python对应的运行速度慢。如何优化它?谢谢 #include <fstream> #include <iostream> #include <vector> #include <string> int main () { std::ifstream infile("longfile.txt"); std::string line; std::vector<std::string> lines; while (std::getline(infile, line)) { lines.push_back(line); } std::cout << lines.size() << std::endl; return 0; },python,c++,optimization,stream,Python,C++,Optimization,Stream,Python: with open('longfile.txt') as f: lines = f.readlines() print len(lines) 运行: 如果您可以提前知道必须读取的行数,则可以在std::vector对象中保留行数。 假设你有10行要读: int main () { std::ifstream infile("longfile.txt"); std::string line; std::vector<std::stri
with open('longfile.txt') as f:
lines = f.readlines()
print len(lines)
运行:
如果您可以提前知道必须读取的行数,则可以在
std::vector
对象中保留行数。
假设你有10行要读:
int main () {
std::ifstream infile("longfile.txt");
std::string line;
std::vector<std::string> lines;
lines.reserve(10);
while (std::getline(infile, line)) {
lines.push_back(line);
}
std::cout << lines.size() << std::endl;
return 0;
}
作者:
默认情况下,对于STL中的大多数容器,复制构造函数或赋值操作符的调用将对数据进行完全复制。
std::move
防止此类复制
您可以通过以下示例轻松检查它:
std::string a("Hello");
std::string b(a);
std::cout<<a.size()<<" "<<b.size()<<std::endl;
std::cout<<"the address of a is : "<<a.c_str()<<" "<<b.c_str()<<std::endl;
std::string d(std::move(a));
std::cout<<a.size()<<" "<<d.size()<<std::endl;
std::string e;
std::string f;
e = b;
std::cout<<e.size()<<" "<<b.size()<<std::endl;
std::cout<<"the address of a is : "<<e.c_str()<<" "<<b.c_str()<<std::endl;
f = std::move(b);
std::cout<<f.size()<<" "<<b.size()<<std::endl;
std::字符串a(“你好”);
std::字符串b(a);
std::cout如果您可以提前知道必须读取的行数,则可以在std::vector
对象中保留行数。
假设你有10行要读:
int main () {
std::ifstream infile("longfile.txt");
std::string line;
std::vector<std::string> lines;
lines.reserve(10);
while (std::getline(infile, line)) {
lines.push_back(line);
}
std::cout << lines.size() << std::endl;
return 0;
}
作者:
默认情况下,对于STL中的大多数容器,复制构造函数或赋值操作符的调用将对数据进行完全复制。
std::move
防止此类复制
您可以通过以下示例轻松检查它:
std::string a("Hello");
std::string b(a);
std::cout<<a.size()<<" "<<b.size()<<std::endl;
std::cout<<"the address of a is : "<<a.c_str()<<" "<<b.c_str()<<std::endl;
std::string d(std::move(a));
std::cout<<a.size()<<" "<<d.size()<<std::endl;
std::string e;
std::string f;
e = b;
std::cout<<e.size()<<" "<<b.size()<<std::endl;
std::cout<<"the address of a is : "<<e.c_str()<<" "<<b.c_str()<<std::endl;
f = std::move(b);
std::cout<<f.size()<<" "<<b.size()<<std::endl;
std::字符串a(“你好”);
std::字符串b(a);
几乎任何优化问题的答案都是“首先,配置文件”。配置你的C++应用程序并确定时间在哪里。
尽管如此,我仍然可以对这里的速度慢做出一些有根据的猜测,并指出这将如何显示在分析器中
慢速getline()
getline()
可能以缓慢的方式实现。例如,它可能需要一次向运行时请求一个字符,因为一旦看起来是换行符,它就需要停止读取。也就是说,它不能在更大的块中请求字节,因为当块的中间出现换行符时,它不能保证“回退”其余块。
运行时几乎肯定会缓冲底层文件的读取,因此这不会像每个字符一次系统调用那么糟糕,但是为文件中的每个字符有效地调用getc
的开销仍然很大
这将在探查器中显示为花费大量时间在getline()
-中,特别是在getline调用的一些类似getc()
-的方法中
python实现根本没有这个问题,因为只进行了一个readlines()
调用,并且实现知道整个文件将被读取,并且可以随意缓冲
冗余复制
另一个可能的候选者是重复复制
第一次运行时调用read()
并将文件块复制到内部缓冲区中。然后,getline()
实现可能会有一个char[]
的内部缓冲区,它在将字符串传递给string
构造函数之前构建字符串,这可能会生成另一个副本(除非运行时使用内部技巧直接传递缓冲区)
然后,正如Johnny_指出的,当你把这些字符串放入向量时,可能会有更多的副本
这将在向量中显示,因为所花费的时间分布在上述各种副本中,例如在string()
构造函数中
实现Python还可以避免大部分冗余副本,因为它具有更高层次的问题视图,而不是C++实现中的分层方法,因此它只可能生成1或2个副本。
解决
这里提到的解决方案解决了上述两个问题。要重新实现Python
readlines
调用,您应该降低一点级别。以char[]
为单位读取文件,并直接在缓冲区中查找换行符。从技术上讲,您根本不需要创建string
对象,因为您只输出找到的行数,但如果确实要创建这些对象,请确保只将char[]
数据复制到每个字符串中一次
您可以使用字符串(const char*s,size\t n)
构造函数直接指向字符缓冲区来完成此操作。最后,正如Johnny_建议的那样,确保在复制到向量中时不要再复制另一个副本。几乎任何优化问题的答案都是“首先,配置文件”。配置你的C++应用程序并确定时间在哪里。
尽管如此,我仍然可以对这里的速度慢做出一些有根据的猜测,并指出这将如何显示在分析器中
慢速getline()
getline()
可能以缓慢的方式实现。例如,它可能需要一次向运行时请求一个字符,因为一旦看起来是换行符,它就需要停止读取。也就是说,它不能在更大的块中请求字节,因为当块的中间出现换行符时,它不能保证“回退”其余块。
运行时几乎肯定会缓冲底层文件的读取,因此这不会像每个字符一次系统调用那么糟糕,但是为文件中的每个字符有效地调用getc
的开销仍然很大
这将在探查器中显示为花费大量时间在getline()
-中,特别是在getline调用的一些类似getc()
-的方法中
python实现根本没有这个问题,因为只进行了一个readlines()
调用,并且实现知道整个文件将被读取,并且可以随意缓冲
冗余复制
另一个可能的候选者是重复复制
第一次运行时调用read()
并将文件块复制到内部缓冲区中。然后getline()
实现可能会有一个内部缓冲区
while (std::getline(infile, line)) {
lines.push_back(std::move(line));
}
std::string a("Hello");
std::string b(a);
std::cout<<a.size()<<" "<<b.size()<<std::endl;
std::cout<<"the address of a is : "<<a.c_str()<<" "<<b.c_str()<<std::endl;
std::string d(std::move(a));
std::cout<<a.size()<<" "<<d.size()<<std::endl;
std::string e;
std::string f;
e = b;
std::cout<<e.size()<<" "<<b.size()<<std::endl;
std::cout<<"the address of a is : "<<e.c_str()<<" "<<b.c_str()<<std::endl;
f = std::move(b);
std::cout<<f.size()<<" "<<b.size()<<std::endl;