Каков самый быстрый способ прочитать 10 ГБ файл с диска?

Нам нужно читать и подсчитывать разные типы сообщений/запускать некоторые статистические данные в текстовом файле 10 ГБ, например, FIX журнал. Мы используем Linux, 32-разрядные, 4 процессора, Intel, кодирование в Perl, но язык не имеет большого значения.

Я нашел несколько интересных советов в Tim Bray Проект WideFinder. Однако мы обнаружили, что использование карт памяти по существу ограничена 32-битной архитектурой.

Мы попытались использовать несколько процессов, которые, похоже, работают быстрее, если мы параллельно обрабатываем файл, используя 4 процесса на 4 процессора. Добавление многопоточности замедляет работу, возможно из-за стоимости переключения контекста. Мы попытались изменить размер пула потоков, но это все еще медленнее, чем простая многопроцессорная версия.

Часть отображения памяти не очень стабильна, иногда она занимает 80 секунд, а иногда и 7 секунд в файле размером 2 ГБ, возможно, из страниц или что-то, что связано с использованием виртуальной памяти. Во всяком случае, Mmap не может масштабироваться за пределы 4 ГБ на 32-битной архитектура.

Мы попробовали Perl IPC:: Mmap и Sys::Mmap. Смотрел в Map-Reduce также, но проблема в самом деле - I/O связанный, сама обработка достаточно быстро.

Итак, мы решили попробовать оптимизировать базовый ввод-вывод, настроив размер буфера, тип и т.д.

Может ли кто-нибудь, кто знает о существующем проекте, где это проблема была эффективно решена на любом языке/платформе указать на полезную ссылку или предложить направление?

Ответ 1

В большинстве случаев вы будете привязаны к I/O, а не ЦП, поэтому просто прочитайте этот файл с помощью обычного ввода/вывода Perl и обработайте его в одном потоке. Если вы не докажете, что можете делать больше операций ввода-вывода, чем ваша работа с одним процессором, не тратьте время на что-то еще. В любом случае, вы должны спросить: почему на Земле это в одном огромном файле? Почему на Земле они не разделяют его разумным образом, когда они его генерируют? Было бы более достойно работать. Затем вы можете поместить его в отдельные каналы ввода-вывода и использовать больше CPU (если вы не используете какой-либо RAID 0 или NAS или...).

Измерьте, не предполагайте. Не забудьте очистить кеши до каждого теста. Помните, что сериализованный ввод-вывод является величиной быстрее, чем случайной.

Ответ 2

Все это зависит от того, какую предварительную обработку вы можете сделать и когда. В некоторых системах мы имеем gzip такие большие текстовые файлы, уменьшая их до 1/5 до 1/7 от их первоначального размера. Часть того, что делает это возможным, нам не нужно обрабатывать эти файлы до тех пор, пока они не будут созданы, и во время создания у нас на самом деле нет никакой другой нагрузки на машины.

Обработка их выполняется более или менее способом zcat themfiles | ourprocessing. (ну, это сделано через unix-сокеты, хотя с настраиваемым zcat). Он торгует временем процессора для времени ввода-вывода диска и для нашей системы, которая того стоит. Там, конечно, много переменных, которые могут сделать это очень плохой дизайн для конкретной системы.

Ответ 3

Возможно, вы уже прочитали этот форум, но если нет:

http://www.perlmonks.org/?node_id=512221

В нем описывается использование Perl, чтобы сделать это по очереди, и пользователи, похоже, думают, что Perl вполне способен на это.

О, можно ли обрабатывать файл из массива RAID? Если у вас несколько зеркальных дисков, скорость чтения может быть улучшена. Конкуренция за дисковые ресурсы может быть причиной того, что ваша попытка нескольких потоков не работает.

Желаем удачи.

Ответ 4

Мне жаль, что я больше не знаю о содержании вашего файла, но не знаю, кроме текста, это похоже на отличную проблему с MapReduce.

PS, самое быстрое чтение любого файла - это линейное чтение. cat file > /dev/null должна быть скорость чтения файла.

Ответ 5

Думали ли вы о потоковой передаче файла и отфильтровываете в дополнительный файл любые интересные результаты? (Повторяйте, пока у вас не будет файла с размером файла).

Ответ 6

В принципе необходимо "Разделить и победить", если у вас есть сеть компьютеров, затем скопируйте файл 10G на максимально возможное количество клиентских компьютеров, чтобы каждый клиентский ПК считывал смещение файла. Для дополнительного бонуса получите EACH pc для реализации многопоточности в дополнение к распределенному чтению.

Ответ 7

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

Поймите, что манипулирование файлом 10 Гб, перенос его через (хотя и в локальную) сеть, изучение сложных решений и т.д. все время.

Ответ 8

У меня есть сотрудник, который ускорил чтение FIX, перейдя в 64-разрядный Linux. Если это стоит того, оставьте немного денег, чтобы получить какое-то причудливое оборудование.

Ответ 9

hmmm, но что не так с командой read() в C? Обычно имеет ограничение 2 ГБ, поэтому просто назовите его 5 раз подряд. Это должно быть довольно быстро.

Ответ 10

Если вы привязаны к вводу/выводу и ваш файл находится на одном диске, вам нечего делать. Простое однопоточное линейное сканирование по всему файлу - это самый быстрый способ получить данные с диска. Использование больших размеров буфера может немного помочь.

Если вы можете убедить автора файла в том, что он разбил его на несколько дисков/машин, вы могли бы подумать о многопоточности чтения (один поток на чтение, каждый поток, считывающий данные из одной полосы).

Ответ 11

Поскольку вы сказали, что платформа и язык не имеют значения...

Если вы хотите, чтобы стабильная производительность была такой же быстрой, как позволяет исходный носитель, единственный способ, которым я знаю, что это можно сделать в Windows, - это перекрытие не-OS-буферизованных выравниваемых последовательных чтений. Вероятно, вы можете добраться до нескольких GB/s с двумя или тремя буферами, за что, в какой-то момент вам понадобится кольцевой буфер (один писатель, читатели 1+), чтобы избежать копирования. Точная реализация зависит от драйвера /API. Если копирование памяти происходит в потоке (как в ядре, так и в usermode), использующем IO, очевидно, что больший буфер должен копировать, тем больше времени тратится на это, а не на IO. Таким образом, оптимальный размер буфера зависит от прошивки и драйвера. В Windows хорошие значения, которые нужно попробовать, кратные 32 КБ для ввода-вывода диска. Буферизация файлов Windows, сопоставление памяти и все это добавляет накладные расходы. Только хорошо, если вы выполняете либо (или оба) несколько чтения одних и тех же данных в режиме произвольного доступа. Таким образом, для чтения большого файла последовательно один раз, вы не хотите, чтобы ОС блокировала что-либо или какие-либо memcpy. Если вы используете С#, есть также штрафы за вызов в ОС из-за маршалинга, поэтому для кода взаимодействия может понадобиться бит оптимизации, если вы не используете С++/CLI.

Некоторые люди предпочитают бросать аппаратное обеспечение на проблемы, но если у вас есть больше времени, чем денег, в некоторых сценариях можно оптимизировать вещи, чтобы на 100-1000 раз лучше работать на одном компьютере с потребительским уровнем, чем компьютеры, рассчитанные на 1000 компьютеров. Причина в том, что, если обработка также чувствительна к задержкам, выход за пределы использования двух ядер, вероятно, добавляет латентность. Вот почему драйверы могут вызывать гигабайт/с, тогда как корпоративное программное обеспечение заканчивается к мегабайтам в момент его завершения. Независимо от того, какая отчетность, бизнес-логика и такое программное обеспечение для предприятия, возможно, также могут быть выполнены на гигабайтах/с на двух основных потребительских процессорах, если они написаны так же, как и в 80-м, написании игры. Самый известный пример, который я слышал о приближении всей их бизнес-логики, - это обмен LMAX forex, который опубликовал некоторые из их кода на основе кольцевого буфера, который, как говорили, был вдохновлен драйверами сетевых карт.

Забывая всю теорию, если вы довольны < 1 ГБ/с, одна из возможных отправных точек в Windows, которую я нашел, ищет источник readfile из winimage, если вы не хотите вставлять в образцы sdk/driver. Может потребоваться исправление исходного кода, чтобы правильно вычислять perf на скорости SSD. Также экспериментируйте с размерами буфера. Переключатели /h с многопоточным и/или перекрываемым (порт завершения) IO с оптимальным размером буфера (попробуйте 32,64,128 КБ и т.д.), Не используя буферизацию файлов Windows, в моем опыте дают наилучший результат при чтении с SSD (холодные данные) при одновременной обработке (используйте/a для обработки Адлера, поскольку в противном случае он также связан с ЦП).

Ответ 12

Кажется, я вспоминаю проект, в котором мы читали большие файлы. Наша реализация использовала многопоточность - в основном n * worker_threads начинались с увеличения смещений файла (0, chunk_size, 2xchunk_size, 3x chunk_size... n-1x chunk_size ) и читал небольшие куски информации. Я не могу точно вспомнить наши аргументы в пользу этого, поскольку кто-то другой все это делал - рабочие были не единственной вещью, но это примерно так, как мы это делали.

Надеюсь, что это поможет

Ответ 13

Не указано в проблеме, что последовательность имеет значение действительно или нет. Так, разделите файл на равные части, скажем, 1 ГБ каждый, и поскольку вы используете несколько процессоров, то несколько потоков не будут проблемой, поэтому читайте каждый файл с использованием отдельного потока и используйте оперативную память емкостью > 10 ГБ, тогда все ваше содержимое будет сохранено в ОЗУ, считываемых несколькими потоками.