Обработка большого текстового файла (& gt; 50 ГБ) в Cpp

Я хочу обработать текстовый файл размером более> 50 ГБ, в основном содержащий последовательности ДНК. Я хочу обработать этот файл по частям, как описано ниже:

  1. Считать X МБ (скажем, 100 МБ) данных в массив (сегмент) (чтение данных)
    не разбивая последнюю строку на кусок)
  2. Создать поток для обработки этого массива (сегмента) (используя open mp: schedule static)

У меня есть ниже вопросы:

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.

Спасибо

1

Решение

Эта тема, кажется, связана с чтением файла
многопоточное чтение с диска?

Кажется, что, поскольку вы только читаете, лучший способ — читать последовательно, до конца, каждый раз, когда у вас есть локальный буфер из X байтов, вы создаете поток вычислений.

Это, конечно, выполнимо, только если каждое вычисление фрагмента является независимым.

0

Другие решения

Предполагая, что вы не выполняете много вычислений для данных во время их чтения, ваша программа почти наверняка будет связана с вводом / выводом, то есть ЦП и ОЗУ будут работать намного быстрее, чем пропускная способность вашего жесткого диска, что совокупная скорость операции будет почти полностью зависеть от скорости чтения данных вашего жесткого диска.

Таким образом, первое, что я бы порекомендовал сделать, это просто определить время, необходимое для того, чтобы просто прочитать весь файл (и вообще ничего не делать с результирующими данными в памяти). Это даст вам ваш «лучший сценарий» — то есть, какую производительность вы могли бы ожидать, если бы ваш код, не связанный с вводом-выводом, был настолько эффективным, что на это вообще не потребовалось время. Тогда вашей целью будет попытаться сделать вашу реальную программу максимально приближенной к этой производительности.

Что касается того, как читать данные с диска, это, вероятно, не имеет значения, поскольку такие вызовы, как fread () и fgets (), используют буферизацию как в стандартной библиотеке C, так и на уровне файловой системы, так что даже если вы читаете в небольшие объемы (например, по одной строке текста за раз), к тому времени, когда запрос достигает реального оборудования ввода-вывода, это более крупный (более эффективный) запрос на чтение с опережением, который в любом случае будет эффективно использовать оборудование. Иными словами, вы можете попробовать прочитать в мегабайтах (или 100 мегабайтах) одним вызовом fread (), если хотите (и затем пройти через гигантский буфер, чтобы разобрать отдельные строки текста), но я думаю, что вы обнаружит, что это не заметно быстрее, чем просто вызов fgets () в цикле, пока вы не доберетесь до конца файла.

(и неизбежному пуристу C ++, который жалуется, что, поскольку этот вопрос помечен как C ++, OP должен использовать вместо этого iostreams … конечно, это тоже стоит попробовать, хотя я считаю, что с iostreams работать неудобно, и некоторые реализации iostream известны быть неэффективным. К счастью, такая проблема достаточно проста, что практично проверить несколько подходов и определить, какой из них обеспечивает наилучшую производительность)

Что касается альтернативных подходов — если вы хотите ускорить процесс быстрее, чем то, что вы можете получить из вышеперечисленного, вам нужно будет начать смотреть на изменение параметров задачи. Поскольку вы (вероятно) связаны с вводом / выводом, лучший способ ускорить процесс — это читать меньше данных. Ваш формат файла действительно должен быть несжатый текст ASCII? Можно ли изменить его на более компактный двоичный формат (например, 2 бита на базовую пару, если я правильно помню свою генетику?), Чтобы размер файла мог быть 12 ГБ вместо 50 ГБ? И / или может ли он храниться в сжатом zlib, что еще больше уменьшит размер файла? Поскольку в наши дни процессоры настолько быстры по сравнению с дисками, чтение меньшего файла и его раздувание zlib, вероятно, будет быстрее, чем чтение большего файла и его дословное использование (!)

0

Если диск вместимость это не проблема, я бы порекомендовал разбить файл на split команда (или подобное).

Например, используйте -l вариант split Команда для создания файлов ~ 100 МБ. Если файл в многострочном формате FASTA, убедитесь, что заголовок и последовательность FASTA находятся в одной строке, а затем укажите четное число для значения -l,

Затем напишите одну программу, которая обрабатывает один фрагмент. Распараллеливайте этот рабочий процесс по мере необходимости (пакетный планировщик и т. Д.) Для обработки всех фрагментов.

0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector