Вот какая проблема — есть файл(порядка 1.5 мега, но это небольшой еще) из него нужно выбрать только те сиволы, которые принадлежат — atgc
но изначально, там есть разная дополнительная информация+форматирование+цифры
как из всего этого безобразия взять только символы из того алфавита?
сейчас код примерно такой:
Здравствуйте pvnic, Вы писали:
P>Здравствуйте!
P>Вот какая проблема — есть файл(порядка 1.5 мега, но это небольшой еще) из него нужно выбрать только те сиволы, которые принадлежат — atgc P>но изначально, там есть разная дополнительная информация+форматирование+цифры P>как из всего этого безобразия взять только символы из того алфавита? P>сейчас код примерно такой:
P>
Здравствуйте pvnic, Вы писали:
P>но заметно тормозит.....
Можно попробовать перед for написать
clearedData.reserve(len);
вполне возможно, что внутри этого for-а при вызове operator+=() несколько раз происходит reallocate, что в общем случае не способствует повышению производительности
Любите книгу — источник знаний (с) М.Горький
Re[2]: как быстро файл проверить на правильность символов
Здравствуйте Boroda, Вы писали:
P>>Вот какая проблема — есть файл(порядка 1.5 мега, но это небольшой еще) из него нужно выбрать только те сиволы, которые принадлежат — atgc P>>но изначально, там есть разная дополнительная информация+форматирование+цифры P>>как из всего этого безобразия взять только символы из того алфавита?
{skipped}
Во-первых, acgt — это не нуклеотиды ли?
Во-вторых. Самые тормоза — в строчке
body += clearedData
Что требует перевыделения памяти.
Как существенно ускорить процесс.
1) выделять выходной буфер по-блочно. можно просто писать в write-only поток.
2) читать файл по-блочно (или вообще отобразить его в память).
С многопоточностью, imho, лучше не заморачиваться — накладные расходы на синхронизацию (на однопроцессорной машине).
3) переписать switch:
int alpha = -1; // индекс буквы в алфавитеswitch(read_letter())
{
case'a': case'A': alpha = 0; break;
case'c': case'C': alpha = 1; break;
case'g': case'G': alpha = 2; break;
case't': case'T': alpha = 3; break;
}
if(alpha < 0) // не то что надоcontinue;
m_iCount[alpha]++; // счетчики по алфавитуstatic const char letters[] = "acgt"; // алфавит в lower-case
write_letter( letters[alpha] );
где псевдофункции read_letter & write_letter могут быть реализованы как вам угодно.
---
Если файл можно зачитать в память одним махом, то чтение-запись делается так (напр.)
char* buffer;
unsigned bufsize;
read_file(&buffer, &bufsize);
const char* reader = buffer;
const char* writer = buffer;
unsigned remains = bufsize;
while(remains)
{
char letter = *(reader++); remains--;
int alpha = -1;
switch(letter)
{
case'A': letter = 'a'; // заодно переведем в lowercasecase'a': alpha = 0;
break;
// аналогично остальные
}
m_iCounts[alpha]++;
// запись
*(writer++) = letter;
}
write_file(buffer, (writer-buffer));
read_file & write_file — это может быть чтение файла или его маппирование — на усмотрение.
Перекуём баги на фичи!
Re[3]: как быстро файл проверить на правильность символов
От:
Аноним
Дата:
03.04.02 08:36
Оценка:
Здравствуйте Кодт, Вы писали:
К>Здравствуйте Boroda, Вы писали:
P>>>Вот какая проблема — есть файл(порядка 1.5 мега, но это небольшой еще) из него нужно выбрать только те сиволы, которые принадлежат — atgc P>>>но изначально, там есть разная дополнительная информация+форматирование+цифры P>>>как из всего этого безобразия взять только символы из того алфавита?
К>{skipped}
К>Во-первых, acgt — это не нуклеотиды ли? ;)
они самые:)
спасибо за развернутый ответ, прийду домой попробую.
Re[3]: как быстро файл проверить на правильность символов
Здравствуйте Кодт, Вы писали:
К>Здравствуйте Boroda, Вы писали:
P>>>Вот какая проблема — есть файл(порядка 1.5 мега, но это небольшой еще) из него нужно выбрать только те сиволы, которые принадлежат — atgc P>>>но изначально, там есть разная дополнительная информация+форматирование+цифры P>>>как из всего этого безобразия взять только символы из того алфавита?
К>{skipped}
К>Во-первых, acgt — это не нуклеотиды ли?
К>Во-вторых. Самые тормоза — в строчке К>
К>body += clearedData
К>
К>Что требует перевыделения памяти.
К>Как существенно ускорить процесс.
К>1) выделять выходной буфер по-блочно. можно просто писать в write-only поток. К>2) читать файл по-блочно (или вообще отобразить его в память).
К>С многопоточностью, imho, лучше не заморачиваться — накладные расходы на синхронизацию (на однопроцессорной машине).
К>3) переписать switch: К>
К>int alpha = -1; // индекс буквы в алфавите
К>switch(read_letter())
К>{
К>case'a': case'A': alpha = 0; break;
К>case'c': case'C': alpha = 1; break;
К>case'g': case'G': alpha = 2; break;
К>case't': case'T': alpha = 3; break;
К>}
К>if(alpha < 0) // не то что надо
К> continue;
К>m_iCount[alpha]++; // счетчики по алфавиту
К>static const char letters[] = "acgt"; // алфавит в lower-case
К>write_letter( letters[alpha] );
К>
К>где псевдофункции read_letter & write_letter могут быть реализованы как вам угодно.
К>---
К>Если файл можно зачитать в память одним махом, то чтение-запись делается так (напр.) К>
К>read_file & write_file — это может быть чтение файла или его маппирование — на усмотрение.
Самое слабое место в его алгоритме это getline, именно оно все тормозит.
Нужно использовать _read, а все остальное по большому счету по барабану как написано.
Все гениальное — просто
Re[4]: как быстро файл проверить на правильность символов
Здравствуйте Kaa, Вы писали:
Kaa>Здравствуйте Кодт, Вы писали:
К>>3) переписать switch: Kaa>Не! Выкинуть его вообще! Вместо этого пользовать
Kaa>strchr( <алфавит>, <текущий_символ> ). Будет заметно побыстрее.
С какой радости это будет быстрее чем свитч?
По любому 8 сравнений + сравнение с нулем — концом строки.
Компактнее — да. Но для 4-буквенного алфавита это несерьезно.
Здравствуйте Kaa, Вы писали:
Kaa>Здравствуйте Кодт, Вы писали:
К>>3) переписать switch: Kaa>Не! Выкинуть его вообще! Вместо этого пользовать
Kaa>strchr( <алфавит>, <текущий_символ> ). Будет заметно побыстрее.
А лучше и это выкинуть! Вместо этого пользовать
strpbrk(<строка>,<алфавит>);
Dimok
Re[5]: как быстро файл проверить на правильность символов
Здравствуйте Boroda, Вы писали:
B>А лучше и это выкинуть! Вместо этого пользовать B>strpbrk(<строка>,<алфавит>);
А все равно быстрее не получится (мне кажется).
Потому что сначала мы каждый символ проверяем на вхождение в алфавит (внутри strpbrk).
а потом, если нашли, — начинаем анализировать, что это за символ и что с ним делать.
Грамотно писаная программа + оптимизирующий компилятор.
Перекуём баги на фичи!
Re[5]: как быстро файл проверить на правильность символов
Я проверил: со свитчем ничто сравниться не может. у моего способа он на 5000000 итераций в 4-5 раз выигрывает. Беру свои слова обратно.
С уважением
Алексей Кирдин
Re: как быстро файл проверить на правильность символов
От:
Аноним
Дата:
04.04.02 09:31
Оценка:
у тебя скорее всего тормозит чтение файла. сделай бинарное чтение (_read()).
а вообще, зачем ты гадаешь? запускай VTune и там смотри, где тормоза расположены.
а чтобы убрать switch сделай предварительно массивчик на 256 элементов, сбрось его
в 0, а элементы 'a','t','g','c','A','T','G','C' установи в 1,2,3,4,1,2,3,4.
При чтении файла используй считанный символ как индекс в этом массиве.
При этом из массива сразу получишь номер буквы (0-skip, 1-a,2-t,3-g,4-c).
А дальше этот номер используй как хочешь (как индекс в массиве счетчиков, например; как условие для if и т.п.)
надеюсь идея ясна.
Re[6]: как быстро файл проверить на правильность символов
Вы не о том спорите, ребята. В switchах оптимизировать нечего, ибо потери не там происходят. Как уже было справедливо указано основные потери происходят в строчках
clearedData+='a';
потому как при этом часто приходится буфер переразмещать.
И это при том, что промежуточный буфер тут вообще не нужен!!!
do
{
getline( is, data );
const char* lpData = data.c_str();
if (data.size()>1 && lpData[0] == '/' && lpData[1] == '/' )
break;
else
{
int len = data.length();
int c=0; for(int i=0; i<len; i++)
{
switch(data[i])
{
case'a':
case'A':
m_iCountA++;
data[c] ='a'; c++;break;
// Тоже самое для остальных букв
}
}
// По выходе из цикла первые c символов data содержат нужные данные,
// обрезаешь data до этого размера и ...
data.resize(c);
body += data;
}
0 программистов ругал сердитый шеф,
потом уволил одного, и стало их FF!
Re[7]: как быстро файл проверить на правильность символов
Здравствуйте zaiats_2k, Вы писали:
Z2>Вы не о том спорите, ребята. В switchах оптимизировать нечего, ибо потери не там происходят.
Z2>И это при том, что промежуточный буфер тут вообще не нужен!!!
И об этом тоже было сказано
.....
data[c] ='a'; c++;
.....
// По выходе из цикла первые c символов data содержат нужные данные,
// обрезаешь data до этого размера и ...
data.resize(c);
body += data;[/b]
Z2>
Во-первых, все равно получается промежуточный буфер, хотя и более редко обновляемый.
Во-вторых, работа с STL — это динамическое выделение памяти, а следовательно, не быстрое.
---
Предполагая, что файл может быть завален нужными буквами полностью, получаем оценку сверху размера буфера.
Одним махом читаем, другим махом — фильтруем, третьим — освобождаем излишки.
Если размеры файлов — многие мегабайты, а плотность нуклеотидов мала, то, наверное, удобнее сначала переписать файл (например, во временный файл со 100% плотностью), а потом юзать уже его.
Или сделать обертку, которая из файла последовательно читает только нужное.
char getACGT(FILE* src);
int getACGTs(FILE* src, char* dst, int size);
Смотря по тому, как используются полученные данные.
Перекуём баги на фичи!
Re[8]: как быстро файл проверить на правильность символов
Я просто сказал в чём была проблема в приведённом в исходном постинге участке кода.
Можно продолжить решать задачу в общем виде или для различных экстремальных случаев... Но нужно ли это спрашивающему? IMHO нет, если он ещё не разобрался в том что скрывается за basic_string::operator+=
0 программистов ругал сердитый шеф,
потом уволил одного, и стало их FF!