Каков самый быстрый способ прочитать 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 ГБ, тогда все ваше содержимое будет сохранено в ОЗУ, считываемых несколькими потоками.