Ответ 1
Используйте GNU parallel
. И вы можете найти еще несколько примеров того, как реализовать его здесь.
find /mnt/data -type f | parallel -j 64 md5sum > md5.txt
скажем, у меня 64-ядерный сервер, и мне нужно вычислить md5sum
всех файлов в /mnt/data
и сохранить результаты в текстовом файле:
find /mnt/data -type f -exec md5sum {} \; > md5.txt
Проблема с приведенной выше командой заключается в том, что в любой момент времени выполняется только один процесс. Я хотел бы использовать всю мощь своих 64-ядер. В идеале я хотел бы убедиться, что в любой момент времени выполняется 64 параллельных процесса md5
(но не более 64).
Кроме того. Мне понадобится вывод из всех процессов, которые будут храниться в один файл.
ПРИМЕЧАНИЕ. Я не ищу способ вычисления md5sum
одного файла параллельно. Я ищу способ вычислить 64 md5sums из 64 разных файлов параллельно, если есть файлы из find
.
Используйте GNU parallel
. И вы можете найти еще несколько примеров того, как реализовать его здесь.
find /mnt/data -type f | parallel -j 64 md5sum > md5.txt
Если вы хотите экспериментировать, попробуйте установить md5deep
. (http://md5deep.sourceforge.net)
Вот руководство, в котором вы можете прочитать:
-jnn Управляет многопоточным. По умолчанию программа создаст один поток производителя для сканирования файловой системы и один поток хеширования на каждый процессор ядро. Многопоточность приводит к тому, что имена файлов вывода не детерминированный порядок, поскольку файлы, которые занимают больше времени для хэша, будут задерживаются, пока они хэшируются. Если требуется детерминированный порядок, укажите -j0, чтобы отключить многопоточность
Если это не помогает, у вас есть узкое место ввода-вывода.
Вы также можете использовать xargs, он может быть более доступным, чем параллели на некоторых дистрибутивах.
-P контролирует количество порожденных процессов.
find /mnt/data -type f | xargs -L1 -P24 md5sum > /tmp/result.txt
ОБНОВЛЕНО
Если вы не хотите использовать дополнительные пакеты, вы можете попробовать sg следующим образом:
#!/usr/bin/bash
max=5;
cpid=()
# Enable job control to receive SIGCHLD
set -m
remove() {
for i in ${!cpid[*]}; do
[ ! -d /proc/$i ] && echo UNSET $i && unset cpid[$i] && break
done
}
trap remove SIGCHLD
for x in $(find ./ -type f -name '*.sh'); do
some_long_process $x&
cpid[$!]="$x";
while [ ${#cpid[*]} -ge $max ]; do
echo DO SOMETHING && sleep 1;
done
done
wait
Сначала он позволяет получать SIGCHLD, если подпроцесс завершается. Если SIGCHLD находит первый несуществующий процесс и удаляется из массива cpid
.
В цикле for он запускает max
число some_long_process
асинхронно. Он max
достиг своего опроса всех pids, добавленных в массив cpid
. Он ожидает, пока длина cpid
будет меньше, чем max
, и асинхронно начнет еще несколько процессов.
Если список окончен, он ждет завершения всех детей.
ADDED