У меня есть список файлов, которые мне нужно скопировать в системе Linux - каждый файл имеет размер от 10 до 100 ГБ.
Я хочу скопировать только в локальную файловую систему. Есть ли способ сделать это параллельно - с несколькими процессами, каждый из которых отвечает за копирование файла - в просто манера?
Я могу легко написать многопоточную программу для этого, но мне интересно узнать, есть ли для этого низкоуровневый метод Linux.
Если ваша система не страдает от этого (например, возможно, файлы находятся в кеше), тогда GNU Parallel http://www.gnu.org/software/parallel/ может работать на вас:
find . -print0 | parallel -0 -j10 cp {} destdir
Это будет запускать 10 одновременных cp
с.
Pro: легко читать.
Против: GNU Parallel не является стандартом для большинства систем, поэтому вам, вероятно, придется его установить.
Посмотрите вступительное видео для получения дополнительной информации: http://www.youtube.com/watch?v=OpaiGYxkSuQ
Смотрите также https://oletange.wordpress.com/2015/07/04/parallel-disk-io-is-it-faster/ для обсуждения параллельного дискового ввода-вывода.
Для этого не существует низкоуровневого механизма по очень простой причине: это снизит производительность вашей системы. В дисках с пластинами каждая запись будет бороться за размещение головки, что приведет к массовому ожиданию ввода-вывода. С твердотельными накопителями это приведет к перегрузке одной или нескольких системных шин, вызывая другие проблемы.
Как уже упоминалось, это ужасная идея. Но я считаю, что каждый должен суметь реализовать свои ужасные планы, ооочень ...
for FILE in *;do cp $FILE <destination> &;done
Звездочку можно заменить на регулярное выражение ваших файлов или $(cat <listfile>)
если у вас все они есть в текстовом документе. Амперсанд запускает команду в фоновом режиме, поэтому цикл будет продолжен, порождая новые копии.
Как уже упоминалось, это полностью уничтожит ваш ввод-вывод. Так что ... я действительно не рекомендую это делать.
- Кристофер Карел
Единственный ответ, который не испортит отзывчивость вашей машины, - это не совсем «копия», но он очень быстрый. Если вы не будете редактировать файлы в новом или старом месте, тогда жесткая ссылка будет фактически копией, и (только) если вы находитесь в той же файловой системе, они создаются очень-очень-очень быстро.
Проверять, выписываться cp -l
и посмотрите, сработает ли это для вас.
Вот инструмент распределенного / параллельного и децентрализованного копирования файлов, который разбивает файл на части и копирует все фрагменты параллельно. Это, вероятно, поможет вам только в том случае, если у вас есть SSD, который поддерживает несколько потоков или какую-то настройку с несколькими головками диска.
Для людей, которые думают, что это не лучшая идея, я бы сказал, это зависит. У вас может быть большая система raid или параллельная файловая система, которая обеспечит действительно лучшую производительность, чем может обработать один процесс cp. Тогда да, вам нужно использовать «параллельный инструмент».
Возьмем этот пример:
timeout 10 strace -e write -c cp /dev/zero /dev/null
strace: Process 24187 detached
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
100.00 0.655188 4 166222 write
------ ----------- ----------- --------- --------- ----------------
100.00 0.655188 166222 total
тогда это
timeout 0.01 strace -e write cp /dev/zero /dev/null
write(4, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 65536) = 65536
write(4, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 65536) = 65536
write(4, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 65536) = 65536
write(4, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 65536) = 65536
write(4, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 65536) = 65536
write(4, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 65536) = 65536
write(4, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 65536) = 65536
strace: Process 24567 detached
поэтому каждый системный вызов, выполняемый "cp", в этом случае составляет 64 КБ, и в течение 10 секунд в моей системе я могу обеспечить эту пропускную способность: 65536 * 166222/10 = 1089352499 = ~ 1,08 ГБ / с
Теперь давайте запустим эту рабочую нагрузку с двумя процессами (у меня 4 ядра, но мой рабочий стол используется для других вещей, и здесь это просто пример):
timeout 10 strace -e write -c cp /dev/zero /dev/null & timeout 10 strace -e write -c cp /dev/zero /dev/null & wait
[1] 26106
[2] 26107
strace: Process 26113 detached
strace: Process 26112 detached
% time seconds usecs/call calls errors syscall
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
------ ----------- ----------- --------- --------- ----------------
100.00 0.624108 4 162616 write
100.00 0.638468 4 162451 write
------ ----------- ----------- --------- --------- ----------------
100.00 0.624108 162616 total
100.00 0.638468 162451 total
------ ----------- ----------- --------- --------- ----------------
[1]- Exit 124 timeout 10 strace -e write -c cp /dev/zero /dev/null
Итак, мы видим, что можем почти вдвое увеличить производительность, используя для этого 2 ядра.
Так что, если мы находимся в контексте, отличном от диска 1xHard на диск 1xHard, но в массиве рейдов (или нескольких NVMe, так что не самый распространенный случай, я согласен, но я работаю над этим каждый день), он определенно показывает лучшую производительность при использовании нескольких общих в параллельно.
Вы должны попробовать это:
$ seq 3 | parallel cp -v /etc/passwd passwd{}
Это скопирует файл passwd 3 раза из каталога / etc / в ваш $ HOME
Или, если ваш файл находится в вашем домашнем каталоге
$ seq 3 | parallel cp -v passwd{,{}}
Это скопирует файл passwd 3 раза в ваш $ HOME