Параллельное копирование файлов

У меня есть список файлов, которые мне нужно скопировать в системе Linux - каждый файл имеет размер от 10 до 100 ГБ.

Я только хочу скопировать в локальную файловую систему. Есть ли способ сделать это параллельно - с несколькими процессами, каждый из которых отвечает за копирование файла - простым способом?

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

6 ответов

Если ваша система не перегружена им (например, возможно, файлы находятся в кеше), тогда GNU Parallel http://www.gnu.org/software/parallel/ может работать для вас:

find . -print0 | parallel -0 -j10 cp {} destdir

Это будет работать 10 одновременно cps.

Pro: это просто читать.

Против: GNU Parallel не является стандартным на большинстве систем - поэтому вам, вероятно, придется его установить.

Посмотрите вступительное видео для получения дополнительной информации: http://www.youtube.com/watch?v=OpaiGYxkSuQ

См. Также https://oletange.wordpress.com/2015/07/04/parallel-disk-io-is-it-faster/ для обсуждения параллельного дискового ввода-вывода.

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

Проверять, выписываться cp -l и посмотрим, сработает ли это для вас.

Для этого нет механизма низкого уровня по очень простой причине: это приведет к снижению производительности вашей системы. При использовании дисков с дисками каждая запись будет бороться за размещение головки, что приводит к массовому ожиданию ввода-вывода. При использовании твердотельных накопителей это приведет к насыщению одной или нескольких системных шин, что вызовет другие проблемы.

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

for FILE in *;do cp $FILE <destination> &;done

Звездочку можно заменить регулярным выражением ваших файлов, или $(cat <listfile>) если у вас есть все они в текстовом документе. Амперсанд запускает команду в фоновом режиме, поэтому цикл будет продолжаться, порождая больше копий.

Как уже упоминалось, это полностью уничтожит ваш ввод-вывод. Так что... я бы не советовал это делать.

- Кристофер Карел

Вот инструмент распределенного / параллельного и децентрализованного копирования файлов, который будет разбивать файл на части и копировать все фрагменты параллельно. Вероятно, это поможет вам, только если у вас есть SSD, который поддерживает несколько потоков, или какая-то установка с несколькими головками дисков.

https://github.com/hpc/dcp

Для людей, которые думают, что это не лучшая идея, я бы сказал, это зависит. У вас может быть большая система 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 | параллельный cp -v /etc/passwd passwd{}

Это скопирует файл passwd 3 раза из каталога / etc / в ваш $HOME

Или, если ваш файл находится в вашем домашнем каталоге

    $ seq 3 | параллельный cp -v passwd{,{}}

Это скопирует файл passwd 3 раза в ваш $HOME

Другие вопросы по тегам