为什么我的C ++文本文件解析脚本比我的Python脚本慢得多?
我目前正在尝试自学c ++,并且正在处理文件IO。 我已经阅读了cplusplus.com教程,并且使用了我在那里学到的基本文件IO技术:
std::ifstream using this to open a read-only file
std::ofstream using this to create an output file
std::getline using this to read each line of the file
outputfile << linecontents using this to write to the output file
我有一个大约10MB的文本文件,其中包含第一百万个素数,它们之间用空白分隔,8个素数分隔到一行。 我的目标是编写一个程序,该程序将打开文件,读取内容,然后用每行一个素数编写一个新文件。 我使用正则表达式去除每行末尾的空白,并用一个换行符替换每个数字之间的空格。
基本的算法很简单:使用正则表达式,我修剪每行末尾的空白,并用换行符替换中间的空白,然后将该字符串写入输出文件。 我用c ++和Python编写了'相同'算法(除了我使用内置的strip()函数去除前导和尾部空白),并且Python程序更快! 我期望的是相反的; 我认为一个(写得很好的)c ++程序应该是闪电般的,一个Python程序要慢10-20倍。 无论Python在幕后做了哪些优化,尽管正在让它比我的'等价的'c ++程序更快。
我的正则表达式搜索:
std::tr1::regex rxLeadingTrailingWS("^(s)+|(s)+$"); //whitespace at beginning or end of string
std::tr1::regex rxWS("(s)+"); //whitespace anywhere
我的文件解析代码:
void ReWritePrimesFile()
{
std::ifstream readFile("..//primes1.txt");
std::ofstream reducedPrimeList("..//newprimelist.txt");
std::string readout;
std::string tempLine;
std::tr1::regex rxLeadingTrailingWS("^(s)+|(s)+$"); //whitespace at beginning or end of string
std::tr1::regex rxWS("(s)+"); //whitespace anywhere
std::tr1::cmatch res; //the variable which a regex_search writes its results to
while (std::getline(readFile, readout)){
tempLine = std::tr1::regex_replace(readout.c_str(), rxLeadingTrailingWS, ""); //remove leading and trailing whitespace
reducedPrimeList << std::tr1::regex_replace(tempLine.c_str(), rxWS, "n") << "n"; //replace all other whitespace with newlines
}
reducedPrimeList.close();
}
但是,此代码需要几分钟的时间来解析10 MB文件。 以下Python脚本大约需要1-3秒(尚未计时):
import re
rxWS = r's+'
with open('pythonprimeoutput.txt', 'w') as newfile:
with open('primes1.txt', 'r') as f:
for line in f.readlines():
newfile.write(re.sub(rxWS, "n", line.strip()) + "n")
唯一显着的区别是我使用内置的strip()函数去除换行符而不是使用正则表达式。 (这是我执行时间非常缓慢的原因吗?)
我不确定我的计划中可怕的低效率来自哪里。 一个10MB的文件不应该花这么长的时间来解析!
*编辑:最初显示的文件为20MB,仅为10MB。
Per Nathan Oliver的建议是,我使用了下面的代码,它仍然需要大约5分钟的时间才能运行。 这与我在Python中使用的算法非常相似。 仍然不确定有什么不同。
void ReWritePrimesFile()
{
std::ifstream readFile("..//primes.txt");
std::ofstream reducedPrimeList("..//newprimelist.txt");
std::string readout;
std::string tempLine;
//std::tr1::regex rxLeadingTrailingWS("^(s)+|(s)+$"); //whitespace at beginning or end of string
std::tr1::regex rxWS("(s)+"); //whitespace anywhere
std::tr1::cmatch res; //the variable which a regex_search writes its results to
while (readFile >> readout){
reducedPrimeList << std::tr1::regex_replace(readout.c_str(), rxWS, "n") + "n"; //replace all whitespace with newlines
}
reducedPrimeList.close();
}
第二次编辑:我不得不在regex_replace行的末尾添加一个额外的换行符。 显然readFile >>读数停在每个空白字符? 不知道它是如何工作的,但它为文件中的每个数字运行while循环的迭代,而不是针对文件中的每一行。
你使用的代码比较慢,因为你在C ++代码中执行了两个正则表达式调用。 只要知道如果使用>>
操作符从文件读取,它将忽略前导空白并阅读,直到找到另一个空白字符。 你可以很容易地写你的功能,如:
void ReWritePrimesFile()
{
std::ifstream readFile("..//primes1.txt");
std::ofstream reducedPrimeList("..//newprimelist.txt");
std::string readout;
while(readFile >> readout)
reducedPrimeList << readout << 'n';
}
链接地址: http://www.djcxy.com/p/5395.html
上一篇: Why is my C++ text file parsing script so much slower than my Python script?