2009-08-28 4 views
11

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

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

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

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

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

Поэтому мы решили попробовать оптимизировать основные ввода/вывод с помощью настройки размера буферного, типа и т.д.

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

+2

Какова производительность на одном процессоре для 2G? Вероятно, вам нужно определить, является ли проблема ввода-вывода или вычислением CPU. – Cervo

+2

Если вы действительно привязаны к диску (IO), лучший способ - купить более быстрые диски, больше дисков (в RAID0, RAID5, RAID10 и т. Д.) Или 64-разрядную машину с достаточной памятью для хранения файла на RAM-диск. Любой разумный одиночный диск должен иметь возможность вытягивать 50 МБ/с; несколько быстрых дисков должны быть способны подтолкнуть вас как минимум до 300 МБ/с. – derobert

+1

Я бы порекомендовал вам не использовать Sys :: Mmap, а File-Map (по причинам, указанным в документации последнего). В любом случае вы, вероятно, не хотите использовать IPC :: Mmap. –

ответ

9

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

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

0

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

Надеется, что это помогает

2

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

3

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

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

Он описывает использование Perl, чтобы сделать линию за линией, и пользователи, кажется, думают Perl вполне способен из этого.

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

Удачи.

3

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

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

+3

Действительно; мой коллега, работающий над подобной проблемой, использовал время от кота, чтобы отслеживать другие проблемы в скорости чтения файлов. NFS был ужасным временем сосать. :( –

1

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

+3

«проблема на самом деле связана с IO» <--- удача скопировать файл на машину быстрее, чем диски могут его прочитать. – derobert

1

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

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

+2

База данных и запросы на запуск могут занимать больше времени, чем вся обработка в perl. (Из моего опыта даже вы используете массовую загрузку и MySQL, который является одним из самых быстрых подходов к тому, что вы можете использовать.) –

+1

Как только у вас есть данные в * приличной * базе данных, вы можете запускать столько запросов, сколько хотите (даже те, которые вы не знали, что вы, возможно, хотели запускать), с небольшими дополнительными затратами. –

1

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

4

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

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

1

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

1

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

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

0

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

1

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

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

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

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

 Смежные вопросы

  • Нет связанных вопросов^_^