Предположим, я хочу найти все совпадения в сжатом текстовом файле:
$ gzcat file.txt.gz | pv --rate -i 5 | grep some-pattern
pv --rate
используется здесь для измерения пропускной способности трубы. На моей машине это около 420Mb / s (после распаковки).
Сейчас я пытаюсь сделать параллельный grep, используя GNU параллельно.
$ gzcat documents.json.gz | pv --rate -i 5 | parallel --pipe -j4 --round-robin grep some-pattern
Теперь пропускная способность упала до ~ 260 Мбит / с. И что самое интересное, parallel
сам процесс использует много процессора. Больше чем grep
процессы (но меньше чем gzcat
).
РЕДАКТИРОВАТЬ 1 : я пробовал разные размеры блока ( --block
), а также разные значения для -N
/ -L
параметров. Ничто не помогает мне в этом пункте.
Что я делаю неправильно?
источник
--pipe
это неэффективно? Я имею в виду, это какая-то фундаментальная проблема или конкретная реализация.--pipe
каждый байт должен проходить один процесс, который должен немного обработать каждый байт. С--pipepart
большинством байтов центральный процесс никогда не видит: они обрабатываются порожденными заданиями. Так как узким местом является довольно небольшое количество строк,--pipe
я бы приветствовал C / C ++-кодер, который переписал бы часть, которая затем будет выполняться для людей, у которых на пути есть C-компилятор.grep очень эффективен - нет смысла запускать его параллельно. В вашей команде только для декомпрессии нужно больше процессора, но это не может быть параллельно.
Для параллельного разделения входных данных требуется больше ресурсов процессора, чем для получения соответствующих строк с помощью grep.
Изменение ситуации, если вы хотите использовать вместо grep что-то, что требует гораздо больше процессоров для каждой линии - тогда параллель будет иметь больше смысла.
Если вы хотите ускорить эту операцию - посмотрите, где узкое место - возможно, это декомпрессия (затем помогает использовать другой инструмент декомпрессии или лучший процессор) или - чтение с диска (затем помогите с помощью другого инструмента декомпрессии или лучшей дисковой системы).
Исходя из моего опыта - иногда лучше использовать lzma (например, -2) для сжатия / распаковки файлов - он имеет более высокую степень сжатия, чем gzip, поэтому гораздо меньше данных нужно читать с диска, а скорость сопоставима.
источник
Декомпрессия является узким местом здесь. Если декомпрессия не распараллелена внутри, вы не достигнете ее самостоятельно. Если у вас есть более одной подобной работы, то, конечно, запустите их параллельно, но ваш конвейер трудно распараллелить. Разделение одного потока на параллельные потоки почти никогда не стоит и может быть очень болезненным при синхронизации и объединении. Иногда нужно просто признать, что несколько ядер не помогут с каждой выполняемой задачей.
В общем, распараллеливание в оболочке должно в основном происходить на уровне независимых процессов.
источник
parallel
. Я согласен, что это, конечно, в первом случае (без параллельного), но во втором (с параллельным) узкое место находится на параллельной стороне. Это следует из наблюдения, что пропускная способность значительно падает, как измеряется с помощьюpv
. Если узкое место находится в декомпрессии, пропускная способность не изменит того, что вы добавляете в конвейер. Полагаю, это очень интуитивное определение пропускной способности - то, что ограничивает пропускную способность больше всего.parallel
может записать в свой канал. В этом случае большинствоgrep
процессов просто ждут, чтобы получить больше, аparallel
работают круглосуточно, чтобы мультиплексировать блоки в несколько каналов (которые являются дополнительными операциями ввода-вывода и могут даже блокировать декомпрессию, если буфер заполнен). Вы также пытались играть с--block
параметром? По умолчанию это1M
так, пока один grep не получит1M
данные, остальные почти наверняка уже завершены. Поэтому мы возвращаемся к тому факту, что нет смысла распараллеливать это.-N
/-L
options. Кажется, что параметры по умолчанию очень близки к локальному оптимуму, который я испытываю :)pv
(сtime
). Таким образом, вы можете увидетьpv
, замедляет ли это себя. Если это так, тоparallel
копирование данных в каналы - это определенно дополнительные издержки. И в любом случае, я вполне уверен, чтоgrep
в этом случае почти в режиме реального времени, особенно если шаблон представляет собой простую строку без большого возврата. Кроме того,parallel
будут чередоваться и портитьgrep
результаты.pv
само по себе не вызывает проблем, спасибо за совет.