C++ C++;加速多个substr()或等效函数调用以解析大字符串

C++ C++;加速多个substr()或等效函数调用以解析大字符串,c++,string,performance,data-structures,substr,C++,String,Performance,Data Structures,Substr,我试图解析从文件加载到内存中的大字符串。我正在用可变长度的滑动窗口解析DNA序列(存储为字符串)。问题是字符串太大,需要很长时间才能遍历它们。我不知道这是否有可能,但是否有可能加快速度 我的意思是,我希望I/O主导我的应用程序,因此我将逐行读取转换为立即将整个文件读入内存,但在测试代码后,我发现它大部分时间都在这样的循环中: size_t currentCharNumber = 0; int16_t windowSize = 50; //seq is a string of length 249

我试图解析从文件加载到内存中的大字符串。我正在用可变长度的滑动窗口解析DNA序列(存储为字符串)。问题是字符串太大,需要很长时间才能遍历它们。我不知道这是否有可能,但是否有可能加快速度

我的意思是,我希望I/O主导我的应用程序,因此我将逐行读取转换为立即将整个文件读入内存,但在测试代码后,我发现它大部分时间都在这样的循环中:

size_t currentCharNumber = 0;
int16_t windowSize = 50;
//seq is a string of length 249250621
while(seq.length() - currentLinePos < windowSize)
{
   string temp = seq.substr(currentLinePos, windowSize);
   //do stuff to temp
   ++currentLinePos;
}
/* Initialize the window to the first windowSize characters. */
std::deque<char> window(seq.begin(), seq.begin() + windowSize);

/* Repeatedly process each window. */
for (size_t i = windowSize; i < seq.length(); ++i) {
    /* Do something to window */

    /* Drop the first character from the window, then add the next character
     * of the sequence.
     */
    window.pop_front();
    window.push_back(seq[i]);     
}
size\u t currentCharNumber=0;
int16_t windowSize=50;
//seq是长度为249250621的字符串
while(seq.length()-currentLinePos
将序列从文件加载到内存只需几秒钟,但解析序列需要约30分钟(即使在注释掉substr()调用下面的处理之后)。我是否遗漏了一些会增加大量开销的内容,或者可能是由于数据的大小

提到我可以忽略带有ATCG以外字符的子字符串是否有帮助?我的意思是,我在代码中进行过滤,但只有在我从substr获得字符串之后


这是我第一次发布,我的C++有点生疏了。任何反馈都将不胜感激。

您可以通过两个指针将滑动窗口划入原始字符串,并使用它,而不是将整个范围复制到单独的字符串中。如果
std::string
构造是一项开销,请避免它


您也可以每次重复使用相同的
std::string
实例(假设窗口大小不变),但这仍然会花费您一次复制操作的成本(不过,对于较小的窗口/长度比,这可能可以忽略不计)

您可能想考虑使用<代码>字符串切换滑动窗口以使用<代码> STD::DeQue/Cuff>。
deque
类型针对插入和删除两端的值进行了优化,因此在这里是一个很好的选择。首先,您可以将前50个字符加载到
deque
,然后可以按如下方式调整循环:

size_t currentCharNumber = 0;
int16_t windowSize = 50;
//seq is a string of length 249250621
while(seq.length() - currentLinePos < windowSize)
{
   string temp = seq.substr(currentLinePos, windowSize);
   //do stuff to temp
   ++currentLinePos;
}
/* Initialize the window to the first windowSize characters. */
std::deque<char> window(seq.begin(), seq.begin() + windowSize);

/* Repeatedly process each window. */
for (size_t i = windowSize; i < seq.length(); ++i) {
    /* Do something to window */

    /* Drop the first character from the window, then add the next character
     * of the sequence.
     */
    window.pop_front();
    window.push_back(seq[i]);     
}
/*将窗口初始化为第一个窗口大小字符*/
std::deque窗口(seq.begin(),seq.begin()+windowSize);
/*重复处理每个窗口*/
对于(大小i=windowSize;i
这使得构造每个窗口的时间为O(1)而不是O(k),其中
k
是窗口中的字符数。这可能会大大减少运行时间,因为窗口中的字符数非常大


希望这有帮助

调用
std::string::substr
可能会导致过多的动态内存分配,至少会复制周围的缓冲区。通常,您可以通过将算法改为使用字符串消除迭代器来减少对
substr
的需要。

substr
std::string::substr
相关吗?也许你的意思是
seq.substr(…)
?不应该将
currentLinePos
增加
windowSize
而不是仅增加1吗?或者你是说
currentCharNumber
?也许你应该告诉我们更大的上下文,这样你就可以改进算法,完全避免使用
substr
。@eq-对不起,这是我应该说的。修复。@sonicwave我实际上想要每个部分序列,可能有n-WindowsSize唯一的字符串。我用过这个,速度快了很多,可能总体加速了约60%。但下游的一切都需要一根弦。我只是不得不改变下游的一切。我还没有尝试过其他人所说的双指针方法。谢谢