Cópia de arquivo paralelo

9

Tenho uma lista de arquivos que preciso copiar em um sistema Linux - cada arquivo varia de 10 a 100 GB de tamanho.

Eu só quero copiar para o sistema de arquivos local. Existe uma maneira de fazer isso em paralelo - com vários processos cada um responsável pela cópia de um arquivo - de uma maneira simples ?

Posso escrever facilmente um programa multithread para fazer isso, mas estou interessado em descobrir se existe um método Linux de baixo nível para fazer isso.

Jon
fonte
1
A cópia de arquivo paralelo não trará uma aceleração significativa. (Pelo menos em teoria, não deveria.)
Tarnay Kálmán
1
@ TarnayKálmán, a menos que você tenha um sistema de arquivos em estilo de cluster, sobreposição, RAID ou "sem medo" ou qualquer um dos itens acima em uma rede com alta latência ou ocupada; ou uma carga de trabalho em que a latência por arquivo é uma parte significativa do tempo de cópia desse arquivo (1e5 + arquivos muito pequenos, back-end direcionado a conteúdo etc.). O processamento simultâneo seria extremamente útil em tais situações.
Rvalue

Respostas:

11

Se o seu sistema não for debatido por ele (por exemplo, talvez os arquivos estejam no cache), o GNU Parallel http://www.gnu.org/software/parallel/ pode funcionar para você:

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

Isso executará 10 cps simultâneos .

Pro: é simples de ler.

Contras: O GNU Parallel não é padrão na maioria dos sistemas - então você provavelmente precisará instalá-lo.

Assista ao vídeo de introdução para obter mais informações: http://www.youtube.com/watch?v=OpaiGYxkSuQ

Consulte também https://oletange.wordpress.com/2015/07/04/parallel-disk-io-is-it-faster/ para obter uma discussão sobre E / S de disco paralelo.

Ole Tange
fonte
3

Não há mecanismo de baixo nível para isso por um motivo muito simples: isso destruirá o desempenho do sistema. Com unidades de prato, cada gravação disputará o posicionamento do cabeçote, levando a uma espera massiva de E / S. Com os SSDs, isso acabará saturando um ou mais barramentos do sistema, causando outros problemas.

Ignacio Vazquez-Abrams
fonte
Err que não parece ser o caso de um único cp no momento, tenho certeza de que há um meio feliz para vários "cp's" paralelos nos quais o canal de E / S não fica completamente saturado ...
Jon
1
Um ônibus saturado é um ônibus feliz. A largura de banda ociosa é desperdiçada.
Rvalue
3

Como mencionado, esta é uma ideia terrível. Mas acredito que todos devem ser capazes de implementar seus próprios planos horríveis, então ...

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

O asterisco pode ser substituído por uma expressão regular dos seus arquivos ou $(cat <listfile>)se você os tiver todos em um documento de texto. O e comercial inicia um comando em segundo plano, portanto o loop continua, gerando mais cópias.

Como mencionado, isso aniquilará completamente seu IO. Então ... eu realmente não recomendaria fazê-lo.

--Christopher Karel

Christopher Karel
fonte
3

A única resposta que não descartará a responsabilidade da sua máquina não é exatamente uma 'cópia', mas é muito rápida. Se você não estiver editando os arquivos no local novo ou antigo, um link físico será efetivamente como uma cópia e (somente) se você estiver no mesmo sistema de arquivos, eles serão criados muito, muito, muito rapidamente.

Confira cp -le veja se funcionará para você.

Slartibartfast
fonte
2

Aqui está uma ferramenta de cópia de arquivo distribuída / paralela e descentralizada que agrupa o arquivo e copia todos os pedaços em paralelo. Provavelmente, isso só será útil se você tiver um SSD compatível com vários fluxos ou algum tipo de configuração com vários cabeçotes de disco.

https://github.com/hpc/dcp

Jon Bringhurst
fonte
1

Para as pessoas que acham que não é uma ótima ideia, eu diria que depende. Você pode ter um grande sistema de invasão ou um sistema de arquivos paralelo que proporcionará um desempenho realmente melhor do que um processo cp pode suportar. Então sim, você precisa usar uma "ferramenta paralela".

Vamos pegar este exemplo:

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

então isso

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

portanto, cada gravação syscall feita por "cp", nesse caso, é de 64KiB e, por 10s no meu sistema, posso fornecer essa largura de banda: 65536 * 166222/10 = 1089352499 = ~ 1,08GB / s

Agora, vamos lançar essa carga de trabalho com 2 processos (eu tenho 4 núcleos, mas minha área de trabalho é usada para outras coisas, e aqui está apenas um exemplo):

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

Então, vemos que somos capazes de quase dobrar o desempenho usando 2 núcleos para lançá-lo.

Portanto, se estivermos em um contexto diferente de unidade 1xHard para unidade 1xHard, mas uma matriz de incursões (ou vários NVMe, então não é o caso mais comum, eu concordo, mas trabalho nisso todos os dias), isso mostra definitivamente um melhor desempenho para usar vários paralelo.

johann peyrard
fonte
-1

Você deve tentar o seguinte:

    $ seq 3 | cp -v paralelo / etc / passwd passwd {}

Isso copiará o arquivo passwd 3 vezes do diretório / etc / para o seu $ HOME

Ou se o seu arquivo estiver no diretório inicial

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

Isso copiará o arquivo passwd 3 vezes para o seu $ HOME

user3749113
fonte