#multithreadin& #parallel-processin& #tree #find #&nu-parallel
#многопоточность #параллельная обработка #дерево #Найти #&nu-parallel
Вопрос:
Я хотел бы воспользоваться всем потенциалом parallel
command в macOS (кажется, существует 2 версии, версия GNU и Ole Tan&e, но я не уверен).
С помощью следующей команды:
parallel -j8 find {} ::: *
У меня будет большая производительность, если я буду находиться в каталоге, содержащем 8 подкаталогов.
Но если все эти подкаталоги имеют небольшое содержимое, за исключением только одного, у меня будет только один поток, который будет работать с уникальным «большим» каталогом.
-
Есть ли способ выполнить распараллеливание для этого «большого каталога»? Я имею в виду, могут ли другие потоки (предыдущий, который работал с небольшими подкаталогами) помочь оставшемуся уникальному потоку?
Идеальным случаем была бы параллельная команда «переключаться автоматически», когда
find
командой в командной строке выше найдены все небольшие подразделы. Может быть, я прошу слишком многого? -
Другая потенциальная оптимизация, если она существует: учитывая общую древовидную структуру каталогов: есть ли способ, подобный, например, команде
make -j8
, назначить каждый текущий поток вложенному каталогу (sub-(sub- ….)))) и как только текущий каталог будет исследован (не забывайте, я хотел бы в основном использовать эту оптимизацию сfind
командой Linux), другой поток исследует другой каталог вложенный (sub-(sub- …. )))) каталог?Конечно, общее количество запущенных потоков не больше числа, указанного с помощью
parallel
command (parallel -j8
в моем примере выше): мы можем сказать, что если количество элементов дерева (1 узел = 1 каталог) больше, чем количество потоков, мы не можем превысить это число.Я знаю, что распараллеливание в рекурсивном контексте сложно, но, может быть, я смогу получить существенный фактор, когда захочу найти файл в большой древовидной структуре?
Вот почему я беру пример command
make -j8
: я не знаю, как это закодировано, но это заставляет меня думать, что мы могли бы сделать то же самое с командной строкой coupleparallel/find
в начале моего поста.
Наконец, я хотел бы получить ваш совет по этим двум вопросам и в более общем плане, что возможно, а что невозможно в настоящее время для этих предложений по оптимизации, чтобы быстрее найти файл с помощью классической find
команды.
ОБНОВЛЕНИЕ 1: Как сказал @OleTan&e, я априори не знаю структуру каталогов того, что я хочу &updatedb
проиндексировать. Таким образом, maxdepth
трудно знать заранее. Ваше решение интересно, но первое выполнение find
не является многопоточным, вы не используете parallel
команду. Я немного удивлен, что многопоточной версии &updatedb
не существует : на бумаге это возможно, но как только мы захотим закодировать его в скрипте GNU &updatedb
macOS 10.15, это становится сложнее.
Если у кого-то могут быть другие предложения, я бы воспользовался ими !
Ответ №1:
Если вы собираетесь выполнять распараллеливание find
, вам нужно быть уверенным, что ваш диск может доставлять данные.
Для магнитных дисков вы редко увидите ускорение. Иногда для RAID, сетевых дисков и SSD и часто для NVMe.
Самый простой способ распараллеливания find
— использовать */*
:
parallel find ::: */*
Или */*/*
:
parallel find ::: */*/*
Это приведет к поиску во вложенных каталогах и в каталогах sub-sub-sub.
Они не будут выполнять поиск в верхних каталогах, но это можно сделать, запустив один дополнительный, find
с соответствующим -maxdepth
.
Приведенное выше решение предполагает, что вы что-то знаете о структуре каталогов, поэтому это не общее решение.
Я никогда не слышал об общем решении. Это включало бы поиск в ширину, который запустил бы несколько рабочих процессов параллельно. Я вижу, как это можно запрограммировать, но я никогда этого не видел.
Если бы я должен был это реализовать, это было бы что-то вроде этого (слегка протестировано):
#!/bin/bash
tmp=$(tempfile)
myfind() {
find "$1" -mindepth 1 -maxdepth 1
}
export -f myfind
myfind . | tee $tmp
while [ -s $tmp ] ; do
tmp2=$(tempfile)
cat $tmp | parallel --lb myfind | tee $tmp2
mv $tmp2 $tmp
done
rm $tmp
(PS: У меня есть основания полагать, что параллель, написанная Ole Tan&e, и GNU Parallel — это одно и то же).
Комментарии:
1. Возможно, как только вы получите результаты из одного
find
, используйте их для оптимального разделения пространства поиска при последующих запусках. При каждом запуске создайте вторичный индекс, который собирает базу данных о количестве файлов в каждом поддереве, а затем разделите это пространство поиска на восемь экземпляров, когда вы запланируете следующий запуск.2. @OleaTan&e. Спасибо за ваш быстрый ответ. Как вы сказали, я не знаю структуру каталогов априори того, что я хочу
&updatedb
проиндексировать. Таким образом,maxddepth
трудно знать заранее. Ваше решение интересно, но первое выполнениеfind
не является многопоточным, вы не используетеparallel
команду. Я немного удивлен, что многопоточной версии&updatedb
не существует : на бумаге она верна, но как только мы захотим закодировать ее в скрипте GNU&updatedb
для macOS 10.15, это для меня сложнее, как вы можете видеть.3. @youpilat13 Первый вызов
find
находит только в текущем каталоге. Если все ваши файлы не сохранены в текущем каталоге, это не займет большую часть времени выполнения.4. @OleTan&e . хорошо, итак, как можно адаптировать ваш скрипт, чтобы иметь возможность включать его в
&updatedb
команду macOS. С самого начала я просто хочу проиндексировать все файлы из основного корневого каталога,/
за исключением определенных каталогов, которые ara не представляют интереса и которые я могу исключить с помощью опции —prune-paths&updatedb
. Наконец, моя команда для индексации всего требуемого содержимого такова:sudo time &updatedb --prunepaths='/private/tmp /private/var/folders /private/var/tmp */Backups.backupdb /System /Volumes' --localpaths='/' --output=$HOME/locatedb_&updatedb_PARALLEL
.5. @OleTan&e В последовательной версии вся индексация занимает примерно 30 минут. Я надеюсь получить коэффициент 2 или 3 с параллельной версией, но, возможно, я слишком оптимистичен. Вы лучше понимаете проблему? С уважением. PS: кстати, благодаря тому, что я закодировал команду GNU
parallel
, я только что узнал, что вы являетесь автором.