Python解析stdin的速度比C++快得多
Python parsing stdin much faster than C++
我有一个python函数,我希望将其翻译成C++,以尝试获得一些额外的速度(因为它将用于解析>100GB的文件(。我对C++非常缺乏经验,在我的基本翻译之后,我发现我的C++函数运行得慢得多,这让我很震惊。任何关于为什么会这样,或者我可以做些什么来改进我的C++代码的建议都将不胜感激。
脚本概述:该函数从另一个程序读取stdin,检查每一行是否有任何子字符串匹配,并将每一行打印到stdout
Python函数:
def find_tagPy(conditions): # conditions e.g. ['TTAT', 'TAT'] etc for line in stdin: # Check conditionss against this line l = line.split("t") if l[0][0] == "@": stdout.write(line) continue FLAG = int(l[1]) if 1 & FLAG: # Read has a pair for bases in conditions: if bases in l[9]: ADD_MATE = 1 stdout.write(line) break # stop looking
C++函数:
void find_tagCpp (vector<string> conditions) {
cin.sync_with_stdio(false);
cin.tie(NULL);
string line;
while (getline(cin, line)) {
vector<string> l;
boost::split(l, line, boost::is_any_of("t"), boost::token_compress_on);
if (l[0][0] == '@') {
cout << line << "n";
continue;
}
int FLAG = stoi(l[1]);
int pair_FLAG = 1;
if (pair_FLAG & FLAG) { // Read has a pair
for (int i=0; i < conditions.size(); i++) { // If bases in SEQ
if (l[9].find(conditions[i]) != string::npos) {
cout << line << "n";
break; // Stop looking
}
}
}
}
}
stdin行的一个示例是:
FCC2CCMACXX:4:105:10758:14389#81 chrM 1 32 10S90M=16151 16062 CATCACGATGGATCACAGGTCTATCACCCATTAACCACTCACGGGAGCTTCATGCATTTGGTATTCGTCTGGGGTGCACGCGATAGCATTG bbb^Wcbbbbcbbcbccbba]WQG^bbcdcb_ ^_
c^`ccdddeeeeffeggggiiiiiiiiihiiiiiiiihighiiiihiggeeebbb NM:i:1 AS:i:85 XS:i:65 RG:Z:1_DB31
在我的机器上,python函数需要1.97秒,C++函数需要11.05秒(文件大小约为25 mb,但这包括使用上游和下游工具进行处理(
编辑:
我发现了boost::split中的一个瓶颈,这有点令人惊讶:
Python:
for i in range(100000):
l = line.split("t")
C++:
for (int i=0; i < 100000; i++) {
vector<string> l;
boost::split(l, line, boost::is_any_of("t"), boost::token_compress_on);
}
Python=0.0325 s
C++=1.245 s
然而,我的文件只有156980行,所以这不可能是全部问题。
split将片段复制到新的字符串中。这很慢,您不需要它们。相反,在行中搜索你想要的作品的开头(第10个(,然后从那里开始调用find。
我意识到我的原始代码不适合测试,所以我想在这里重构它,并讨论我的发现。我按照建议使用-Oast(最快、积极的优化,Apple LLVM 6.1(打开了编译器优化,相比之下,Python是2.7.10。
Python函数
import time
def fun(line):
l = line.split(" ", 10)
if 'TTAGGG' in l[9]:
pass
line = "FCC2CCMACXX:4:1105:10758:14389# 81 chrM 1 32 10S90M = 16151 16062 CATCACGATGGATCACAGGTCTATCACCCTATTAACCACTCACGGGAGCTTTCCATGCATTTGGTATTTTCGTCTGGGGGGTGTGCACGCTTAGGGGATAGCATTG bbb^Wcbbbbccbbbcbccbba]WQG^bbcdcb_^_c_^`ccdddeeeeeffggggiiiiihiiiiihiiihihiiiihghhiihgfgfgeeeeebbb NM:i:1 AS:i:85 XS:i:65 RG:Z:1_DB31"
time0 = time.time()
for i in range(100000):
fun(line)
print time.time() - time0
C++函数
void fun(string* line, string* substring) {
vector<string> l;
boost::split(l, *line, boost::is_any_of(" "));
if (l[9].find(*substring) != string::npos) {
// Do nothing
}
}
int main(int argc, const char * argv[]) {
string line = "FCC2CCMACXX:4:1105:10758:14389# 81 chrM 1 32 10S90M = 16151 16062 CATCACGATGGATCACAGGTCTATCACCCTATTAACCACTCACGGGAGCTTTCCATGCATTTGGTATTTTCGTCTGGGGGGTGTGCACGCTTAGGGGATAGCATTG bbb^Wcbbbbccbbbcbccbba]WQG^bbcdcb_^_c_^`ccdddeeeeeffggggiiiiihiiiiihiiihihiiiihghhiihgfgfgeeeeebbb NM:i:1 AS:i:85 XS:i:65 RG:Z:1_DB31";
string substring = "TTAGGG";
boost::timer t;
for (int i=0; i<100000; i++) {
fun(&line, &substring);
}
cout << t.elapsed() << endl;
return 0;
}
在我的机器上,我现在将c++函数的时间定为205毫秒,将python函数的时间设为66毫秒。有趣的是,现在几乎整个运行时间都被boost::split函数占用了。
如果我去掉这个函数,使用string.find搜索整行(但不是我想要的(:
if ((*line).find(*substring) != string::npos) {
// Do nothing
}
c++运行时减少到大约<1毫秒!因此,它似乎起到了推波助澜的作用:分裂是唯一的问题。谢谢你的建议。
使用一些优化尝试此代码
C++函数:
void find_tagCpp (vector<string> conditions) {
cin.sync_with_stdio(false);
cin.tie(NULL);
string line;
vector<string> l;
while (getline(cin, line)) {
l.clear();
boost::split(l, line, boost::is_any_of("t"), boost::token_compress_on);
if (l[0][0] == '@') {
cout << line << "n";
continue;
}
int FLAG = stoi(l[1]);
int pair_FLAG = 1;
if (pair_FLAG & FLAG) { // Read has a pair
for (int i=0; i < conditions.size(); i++) { // If bases in SEQ
if (l[9].find(conditions[i]) != string::npos) {
printf("%sn", line.c_str());
break; // Stop looking
}
}
}
}
}
- 为什么通过引用返回向量比通过移动返回要快得多?
- 禁用优化后,quick-bench.com 基准测试要快得多
- C++ OpenMP 斐波那契:1 个线程的执行速度比 4 个线程快得多
- 为什么迭代 std::array 比迭代 std::vector 快得多?
- 为什么<wstring>使用自定义 wcscmp 和 wmemcmp 比较器对向量进行排序比默认快得多?
- C 为什么在原始双阵列中的分配似乎比双变量分配要快得多
- Linux 在从文件中读取数据并放入矢量时比 Windows 快得多.txt.我将如何加速Windows以做同样的事情
- 为什么 C 数组比 std::array 快得多?
- 为什么 pcre 正则表达式比 c++11 正则表达式快得多
- 为什么数组比向量快得多
- 为什么 ifstream::read 比使用迭代器快得多
- 为什么其中一个比另一个快得多
- GDI+Image比C#Image快得多
- 为什么堆栈内存的 memcpy 比堆内存快得多
- 为什么使用TBB的OpenCV函数比基于Boost的实现快得多
- 为什么多个文件的编译速度比合并文件快得多
- 为什么Windows C++多线程IOPS比IOMeter快得多
- 为什么STL算法使用指针比std::向量迭代器快得多
- 为什么使用 mkdir () 函数比使用 system ('mkdir 路径')快得多?
- 为什么Eigens-mean()方法比sum()快得多