Я хочу обработать текстовый файл размером более> 50 ГБ, в основном содержащий последовательности ДНК. Я хочу обработать этот файл по частям, как описано ниже:
У меня есть ниже вопросы:
1. How to read a file chunk by chunk efficiently?
2. Alternative approach that i should follow.
3. Any algo/framework that i should go for.
Спасибо
Эта тема, кажется, связана с чтением файла
многопоточное чтение с диска?
Кажется, что, поскольку вы только читаете, лучший способ — читать последовательно, до конца, каждый раз, когда у вас есть локальный буфер из X байтов, вы создаете поток вычислений.
Это, конечно, выполнимо, только если каждое вычисление фрагмента является независимым.
Предполагая, что вы не выполняете много вычислений для данных во время их чтения, ваша программа почти наверняка будет связана с вводом / выводом, то есть ЦП и ОЗУ будут работать намного быстрее, чем пропускная способность вашего жесткого диска, что совокупная скорость операции будет почти полностью зависеть от скорости чтения данных вашего жесткого диска.
Таким образом, первое, что я бы порекомендовал сделать, это просто определить время, необходимое для того, чтобы просто прочитать весь файл (и вообще ничего не делать с результирующими данными в памяти). Это даст вам ваш «лучший сценарий» — то есть, какую производительность вы могли бы ожидать, если бы ваш код, не связанный с вводом-выводом, был настолько эффективным, что на это вообще не потребовалось время. Тогда вашей целью будет попытаться сделать вашу реальную программу максимально приближенной к этой производительности.
Что касается того, как читать данные с диска, это, вероятно, не имеет значения, поскольку такие вызовы, как fread () и fgets (), используют буферизацию как в стандартной библиотеке C, так и на уровне файловой системы, так что даже если вы читаете в небольшие объемы (например, по одной строке текста за раз), к тому времени, когда запрос достигает реального оборудования ввода-вывода, это более крупный (более эффективный) запрос на чтение с опережением, который в любом случае будет эффективно использовать оборудование. Иными словами, вы можете попробовать прочитать в мегабайтах (или 100 мегабайтах) одним вызовом fread (), если хотите (и затем пройти через гигантский буфер, чтобы разобрать отдельные строки текста), но я думаю, что вы обнаружит, что это не заметно быстрее, чем просто вызов fgets () в цикле, пока вы не доберетесь до конца файла.
(и неизбежному пуристу C ++, который жалуется, что, поскольку этот вопрос помечен как C ++, OP должен использовать вместо этого iostreams … конечно, это тоже стоит попробовать, хотя я считаю, что с iostreams работать неудобно, и некоторые реализации iostream известны быть неэффективным. К счастью, такая проблема достаточно проста, что практично проверить несколько подходов и определить, какой из них обеспечивает наилучшую производительность)
Что касается альтернативных подходов — если вы хотите ускорить процесс быстрее, чем то, что вы можете получить из вышеперечисленного, вам нужно будет начать смотреть на изменение параметров задачи. Поскольку вы (вероятно) связаны с вводом / выводом, лучший способ ускорить процесс — это читать меньше данных. Ваш формат файла действительно должен быть несжатый текст ASCII? Можно ли изменить его на более компактный двоичный формат (например, 2 бита на базовую пару, если я правильно помню свою генетику?), Чтобы размер файла мог быть 12 ГБ вместо 50 ГБ? И / или может ли он храниться в сжатом zlib, что еще больше уменьшит размер файла? Поскольку в наши дни процессоры настолько быстры по сравнению с дисками, чтение меньшего файла и его раздувание zlib, вероятно, будет быстрее, чем чтение большего файла и его дословное использование (!)
Если диск вместимость это не проблема, я бы порекомендовал разбить файл на split
команда (или подобное).
Например, используйте -l
вариант split
Команда для создания файлов ~ 100 МБ. Если файл в многострочном формате FASTA, убедитесь, что заголовок и последовательность FASTA находятся в одной строке, а затем укажите четное число для значения -l
,
Затем напишите одну программу, которая обрабатывает один фрагмент. Распараллеливайте этот рабочий процесс по мере необходимости (пакетный планировщик и т. Д.) Для обработки всех фрагментов.