Como paralelizar dd?

Como paralelizar dd?

Atualmente estou tendo problemas para ddinvocar um arquivo esparso como input( if) e um arquivo como output( of) com conv=sparse. ddparece estar usando apenas um núcleo da CPU ( Intel(R) Core(TM) i7-3632QM CPU @ 2.20GHz4 núcleos + 4 Intel Hyperthreads) (100% de 1 núcleo), então estou me perguntando se é possível paralelizar dd. eu estive

  • olhando para info dde man ddparece haver uma função integrada na versão do corutils 8.23
  • verificando sgp_ddo sg3-utilspacote (sem entender se ele atende às minhas necessidades), mas parece não ser capaz de lidar com arquivos esparsos
  • dcflddnão parece ter recursos de paralelização

Até onde sei

  • uma versão/fork aprimorada com manipulação interna de partes do programa em vários threads (evita mudanças de contexto que prejudicam o desempenho de E/S) é preferível a
  • uma solução com GNU parallelrodando localmente é preferível a
  • um sniplet de código personalizado (possivelmente não testado)

Como evitar que a CPU seja o gargalo de uma operação intensiva de E/S? Eu gostaria de executar o comando no Ubuntu 14.04 com Linux 3.13 e manipular imagens de disco de arquivos esparsos com ele em qualquer sistema de arquivos que suporte arquivos esparsos (pelo menos a solução não deve estar vinculada a um sistema de arquivos específico).

Antecedentes: Estou tentando criar uma cópia de um arquivo esparso de 11 TB (contendo cerca de 2 TB de dados) em um zfs (versão instável do zfsonlinux 0.6.4, possivelmente com bugs e a causa do gargalo da CPU (eventualmente pesquisa lenta de buracos)). Isso não deve mudar nada na questão de como paralelizar o dd (de uma forma muito genérica).

Responder1

Testado no Bash:

INFILE=in
seq 0 1000 $((`stat --format %s $INFILE` /100000 )) |
  parallel -k dd if=$INFILE bs=100000 skip={} conv=sparse seek={} count=1000 of=out

Você provavelmente precisará ajustar 1000.

Responder2

Um sniplet de código personalizado e não testado está chegando:

dd if=oldf conv=sparse bs=1k                 count=3000000000                 of=newf &
dd if=oldf conv=sparse bs=1k skip=3000000000 count=3000000000 seek=3000000000 of=newf &
dd if=oldf conv=sparse bs=1k skip=6000000000 count=3000000000 seek=6000000000 of=newf &
dd if=oldf conv=sparse bs=1k skip=9000000000 count=3000000000 seek=9000000000 of=newf &
wait

Isso deve particionar logicamente o arquivo em quatro pedaços de 3 TB e processá-los em paralelo. ( skip=pula os blocos de entrada; seek=procura os blocos de saída.) O quarto comando irá, é claro, ler até o final do arquivo antigo, portanto o count=parâmetro não é estritamente necessário.

informação relacionada