Назад | Перейти на главную страницу

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

У меня есть список файлов, которые мне нужно скопировать в системе 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, который поддерживает несколько потоков или какую-то настройку с несколькими головками диска.

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 | parallel cp -v /etc/passwd passwd{}

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

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

    $ seq 3 | parallel cp -v passwd{,{}}

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