Faça telas diferentes em diferentes núcleos de CPU?

0

Estou conectando a um servidor (osX) com muitos CPUs. Eu quero executar o meu programa para muitos arquivos de entrada diferentes. Agora eu corro um por um:

for input in "${inputs[@]}"
do
    .<my-program.sh> --input $input
done

Isso é muito lento e não usa a potência total da CPU, então gostaria de rodar em paralelo.

Gostaria de abrir uma nova tela desanexada e executar meu programa dentro de algo como:

for input in "${inputs[@]}"
do
    screen -S test -X screen .<my-program.sh> --input $input
done

Cada tela funcionaria em uma CPU diferente (eu gostaria de usar a potência da CPU disponível) e o comando está correto? Ou devo abrir um novo shell para cada entrada (acho que então ele é executado em CPUs diferentes)?

    
por Milena 25.08.2017 / 10:08

2 respostas

1

Para responder diretamente à sua pergunta, a menos que você use pinagem de CPU para atribuir manualmente um processo específico a uma CPU específica, seu sistema operacional normalmente agendará tarefas para serem executadas em qualquer que seja a CPU "melhor" para lidar com isso naquele momento e é possível que a tarefa possa ser movida de um lado para o outro entre vários núcleos de CPU, dependendo do que mais a máquina está fazendo ao mesmo tempo.

O resultado prático disso é que, se você executar cinco instâncias do seu programa, elas poderão rodar em cinco CPUs separadas, mas não há garantia de que serão executadas em CPUs separadas. Se cada processo individual usar menos de 20% da capacidade da CPU, é possível (embora improvável) que todos os cinco funcionem no mesmo processador.

Para resolver sua situação mais ampla, se você tiver um programa que processe vários arquivos e use apenas uma pequena quantidade de energia da CPU, há uma boa chance de que seu gargalo seja a capacidade de E / S de disco. Se esse for o caso, acelerá-lo exigirá um disco mais rápido (ou maior cache de disco, se você estiver repetidamente lendo os mesmos dados) e paralelizá-lo em vários processos e CPUs pode realmente reduzir o desempenho forçando o disco a gastar tempo desligando a leitura dos arquivos de entrada da primeira instância e lendo outros arquivos para cada um dos outros processos.

Uma maneira rápida e fácil de testar se você está sendo afunilado por E / S de disco é cat file_1 file_2 file_3... >/dev/null (onde file_1 , etc. é uma lista de todos os arquivos processados pelo seu programa) e comparar o tempo leva apenas para ler os arquivos (sem fazer qualquer processamento) para o tempo que leva para processá-los.

    
por 25.08.2017 / 14:40
1

Sempre que você executar vários processos, eles serão potencialmente executados em núcleos diferentes. Até mesmo um único processo pode migrar do núcleo para o núcleo muitas vezes por segundo. Isso também se aplica a segmentos individuais dentro de um processo. O kernel sempre tentará executar o maior número possível de threads em paralelo. Por exemplo, se você tem 4 núcleos e 3 segmentos atualmente requerem tempo de CPU, então 3 núcleos estarão ocupados. Se 6 threads precisarem de tempo de CPU, todos os 4 núcleos estarão ocupados e 2 threads aguardarão a sua vez.

Iniciar os programas a partir de diferentes shells ou de diferentes janelas de tela não afeta o modo como os programas são agendados. O que faz com que os programas sejam executados em paralelo no segundo snippet é o fato de que cada chamada para screen inicia uma instância de myprogram.sh e não espera que ela termine. Você poderia fazer a mesma coisa sem envolver a tela, apenas usando o operador & no shell para executar o programa em segundo plano, ou seja, para iniciar o programa e ir imediatamente para a próxima instrução no script sem esperar que o programa fim.

for input in "${inputs[@]}"
do
  .<my-program.sh> --input "$input" &
done

Começar todas as corridas ao mesmo tempo não é necessariamente o caminho mais rápido. Depende dos recursos que seu programa usa. Se o programa usar o tempo de CPU e não fizer muita entrada / saída, obterá melhores resultados executando tantas instâncias quanto o número de núcleos. Se o programa usa muita memória, execute apenas quantas instâncias se encaixarem na memória; se a máquina tiver que trocar ou não tiver espaço suficiente para o cache de disco, ela será executada muito mais lentamente. Se o programa for intensivo de E / S, certifique-se de não saturar a largura de banda de E / S que seja o gargalo (rede, disco,…).

Existem ferramentas que facilitam a execução de um número definido de instâncias de um programa em paralelo. Você pode usar xargs :

printf '%s
all = $(patsubst %.in,%.out,$(wildcard *.in))
%.out: %.in
        myprogram.sh --input $< --output $@
0' "${inputs[@]}" | xargs -0 -L 1 -P 4 myprogram.sh

make também pode executar programas em paralelo. Com o seguinte arquivo chamado Makefile (substitua 8 espaços no início de uma linha por um caractere de tabulação):

for input in "${inputs[@]}"
do
  .<my-program.sh> --input "$input" &
done

Execute make -j4 all para executar myprogram.sh em todos os arquivos .in e produza arquivos .out correspondentes, executando até 4 instâncias em paralelo.

Para cenários mais complexos, você pode querer instalar o paralelo GNU .

    
por 27.08.2017 / 03:32