【发布时间】:2015-07-16 12:04:13
【问题描述】:
我有一个 python 函数,我希望将其翻译成 C++ 以尝试获得一些额外的速度(因为它将用于解析 >100GB 的文件)。我对 C++ 非常缺乏经验,并且很震惊地发现我的 C++ 函数在我的基本翻译之后运行得慢得多。任何关于为什么会这样,或者我可以做些什么来改进我的 C++ 代码的指针将不胜感激。
脚本概述:该函数从另一个程序读取标准输入,检查每一行是否有任何子字符串匹配,并将每一行打印到标准输出
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
}
}
}
}
}
标准输入行的一个例子是:
FCC2CCMACXX:4:1105:10758:14389#81 CHRM 1 32 10S90M = 16151 16062 CATCACGATGGATCACAGGTCTATCACCCTATTAACCACTCACGGGAGCTTTCCATGCATTTGGTATTTTCGTCTGGGGGGTGTGCACGCGATAGCATTG BBB ^ Wcbbbbccbbbcbccbba] WQG ^ bbcdcb_ ^_ C_ ^`ccdddeeeeeffggggiiiiihiiiiihiiihihiiiihghhiihgfgfgeeeeebbb NM:I:1为: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 秒
C++ = 1.245 秒
但是我的文件只有 156,980 行,所以这不是问题的全部。
【问题讨论】:
-
看代码,我会把钱花在
std::string性能上。 -
plus1 用于编译器标志。根据我的经验,
-O0 -g3代码甚至可能比 C# 代码慢。 -
@ChrisMaes
vector“不是很快”到底是怎么回事? -
@kezzos 您的代码中存在一些微不足道的低效问题,但我主要关注
boost::splitstackoverflow.com/questions/7930796/… -
Python 是否有可能将表达式
bases in l[9]优化为一个有限状态机,该机器可以及时搜索与干草堆字符串长度近似线性的任何碱基? C++ 代码明确地单独检查每个碱基,这在 haystack 字符串的长度上也近似线性,但具有与碱基数量成比例的更高常数因子。