Posso usar todos os 4 núcleos da CPU do Raspberry Pi?

11

Eu queria saber se existe uma maneira simples de "ativar" todos os 100% da CPU para que eu possa executar processos mais rapidamente (como cálculos em python).

1) Isso é possível?

2) Existe uma maneira fácil de voltar ao normal?

3) Existe uma maneira de usar menos CPU, se desejado?

Estou pensando em uma interação de linha de comando como:

pi@raspberry:~ $ sudo turnOnFourCores python run.py

NaN
fonte
1
A resposta curta é Não
Steve Robillard
16
A resposta longa é "Se fosse assim tão simples, seria o padrão"
Shadow
18
Ambos os seus comentários são enganosos e podem sugerir que o Pi possui 4 núcleos, mas apenas usa 1. Uma resposta melhor é que todos os quatro núcleos já estão ativos, mas que o Python (e qualquer outro programa, por sinal) usará apenas mais de 1 núcleo, a menos que sejam multithread. O Python ainda pode ser bloqueado efetivamente usando um único núcleo, mesmo com vários threads, devido ao bloqueio global de intérpretes, mas isso está um pouco além do escopo desta pergunta.
Sohcahtoa82
13
Para esclarecer, acho que o OP tem um mal-entendido como as CPUs com vários núcleos funcionam, e suas respostas apenas reforçam seu mal-entendido.
Sohcahtoa82
6
A maneira mais fácil de tornar um programa Python mais rápido é reescrever em uma linguagem compilada (ou pelo menos agilizar as tarefas críticas usando o módulo CA).
Milliways

Respostas:

21

Por padrão, qualquer computador tentará usar todos os seus núcleos quando puder. No entanto, isso só é possível quando um aplicativo é multiencadeado. Se não for (ou seja, um script Python que não use o threadingmódulo), ele poderá usar no máximo apenas um núcleo. Isso equivale a 25% da CPU em uma CPU de quatro núcleos. Se você deseja modificar seu script para usar vários núcleos, divida seu cálculo em várias partes e faça várias threads, como mostra a documentação do Python .

Atualizar:

Como Anon respondeu , isso não funcionará sem o trabalho com o GIL (Global Interpreter Lock) do Python. Isso permite que as tarefas operem (aparentemente) ao mesmo tempo, mas não permite que o código seja executado em vários núcleos. Se você estiver usando módulos escritos em C (por exemplo, numpy), eles poderão permitir o uso de vários núcleos, contornando essa limitação. Além disso, se essa não for uma opção, o Python oferece multiprocessamento , o que permite executar qualquer tarefa em vários núcleos.

lights0123
fonte
A atualização - que está correta - explica por que a primeira parte da resposta está errada em relação ao Python. Você apenas contorna essa limitação do Python escrevendo os módulos C ou alguma linguagem compilada; nesse momento, você não está mais escrevendo o Python. Se o desempenho for crítico, ir para uma linguagem compilada é a resposta certa. (Multiprocessamento é não o mesmo a partir de uma perspectiva de utilização de recursos.)
tijolo
4
@Brick Apenas para esclarecer, uma linguagem compilada certamente não é um requisito para multithreading em processo adequado. Heck, mesmo o GIL do Python é um detalhe de implementação (concedido, para o popular CPython) - existem outros intérpretes do Python que se alegrarão multithread, por exemplo, Jython e IronPython.
22417 Bob
4
Adicionando à confusão, o Python é compilado; no caso do CPython, ele é compilado no bytecode do CPython, que é executado na VM do CPython. Para o Jython, ele é compilado no bytecode Java, que é executado na JVM. E, finalmente, o IronPython compila para o CIL, que tem como alvo o tempo de execução do .NET. Assim, "indo para uma linguagem compilada" para o desempenho realmente não faz sentido;)
marcelm
qualquer computador tentará usar todos os seus núcleos quando puder. Na verdade, ele só usará todos os seus núcleos (ou fará qualquer outra coisa) quando for solicitado . Essa distinção pode parecer óbvia ou até paternalista para os experientes, mas parece que o OP precisa entender que isso não acontece automaticamente.
nekomatic
13

Eu queria saber se existe uma maneira simples de "ativar" todos os 100% da CPU para que eu possa executar processos mais rapidamente (como cálculos em python).

Não no sentido em que acho que você está implicando. Esse também não é um problema específico do pi, é uma restrição lógica.

Por si só, os computadores atualmente não têm muita capacidade para determinar que um processo em execução como um único encadeamento possa ser executado em paralelo. Observe que no momento em que eles podem ter essa capacidade, não há necessidade de programadores de computador, porque um sistema de computador que pode fazer isso também pode escrever seu próprio código 1 ..

Considere a seguinte expressão matemática simples:

(4 + 2) * 17 / (3 + 6)

Existe algum potencial para que isso seja calculado em paralelo, mas é logicamente limitado. Eu diria que não há sentido em mais de dois threads, e mesmo assim ele será apenas um:

#1 a) 4 + 2 b) 6 * 17 c) 102 / 9
#2 a) 3 + 6

O segmento 2 contribuiu calculando 3 + 6 = 9, usado na etapa C pelo segmento 1, salvando-o em uma etapa. Mas isso é o mais longe que o paralelismo chegará aqui. Embora o segmento 2 possa calcular 17/9 enquanto o número 1 faz 6 * 17, isso seria inútil, porque agora você tem dois caminhos diferentes para o mesmo objetivo que não podem ser recombinados. Ou seja, o número 2 poderia continuar trabalhando:

b) 17 / 9 c) 1.888 * 6

E acabam com o mesmo resultado que o segmento nº 1 (11.333), mas eles não se ajudaram além da etapa A, portanto, fazer com que dois deles perseguissem esse objetivo é uma perda de tempo.

(Observe que este exemplo não é literal; ele pretende demonstrar um princípio lógico. A escala na qual as tarefas são encadeadas no código do usuário é muito maior, mas você não precisa de uma lição real de programação multithread para poder compreenda a ideia aqui.)

A exploração de vários processadores requer código escrito para isso. Você não pode simplesmente pegar qualquer coisa e dizer: "use todos os 4 núcleos e faça-o mais rápido!". Não é isso que aconteceria. Logicamente, muitos (... ou a maioria) problemas e tarefas envolvem etapas que não podem ocorrer em paralelo; elas devem ocorrer em sequência.


1. Mas veja o comentário de Felix Dombek abaixo; Eu não sou um especialista em IA. Também pode ser interessante notar que, de acordo com os comentários de Peter Corde, os conjuntos de instruções e processadores contemporâneos podem ser explorados pelo sistema operacional para otimizar coisas muito refinadas de maneira paralela, e os pipelines de hardware fazem isso também, embora não entre núcleos (um único o core tem mais de uma coisa acontecendo, operando no fluxo de instruções em vários pontos antes da execução final). Eu estava tentando me ater ao tópico de threads de usuário aqui, pois acho que isso é mais ou menos o que você está entendendo.

Cachinhos Dourados
fonte
4
Eu escrevi muitos códigos numéricos paralelos, e isso é um pouco enganador quanto aos detalhes. Você não paralela no nível de operações aritméticas individuais como esta. (Se expandirmos além do Raspberry Pi, alguns complementadores e processadores já irão paralelizar parte disso mesmo fora das estruturas de encadeamento.) Você paralela tarefas inteiras em pedaços maiores.
Tijolo
4
@Brick "Você não paralela no nível das operações aritméticas individuais como esta." -> Claro que não, mas vou deixar mais explícito que isso é uma analogia, não uma lição sobre programação multithread de parafusos e porcas.
goldilocks
4
O paralelismo na computação que você usa como exemplo é tão localizado que cria um paralelismo em nível de instrução em um programa que o calcula, e as CPUs com execução fora de ordem podem explorar esse paralelismo por conta própria.
precisa
2
O RPi3 usa um superscalar 2-wide em ordem en.wikipedia.org/wiki/ARM_Cortex-A53 , portanto, com o agendamento cuidadoso das instruções, um compilador ainda pode explorar o ILP colocando duas addinstruções próximas uma da outra, para que ambas possam executar na mesma ciclo do relógio. O seguinte multiplicar e dividir resto será serializado por dependências de dados, como você aponta.
precisa
1
Determinar partes paralelizáveis ​​não requer necessariamente uma IA forte. No sentido "geral", poderia; mas é fácil imaginar que os computadores possam usar uma abordagem heurística que funciona principalmente em muitos casos práticos. Como um computador não provou o último teorema de Fermat, mas certamente existem programas de prova de teoremas. Observe que os compiladores modernos para linguagens de programação já realizam um grande rearranjo de código como parte de suas etapas de otimização, o que envolve raciocinar sobre partes paralelizáveis.
Felix Dombek
7

Não para python.

Outras pessoas estão sugerindo que você procure por threading, que é uma resposta válida para a maioria dos idiomas, mas eles não levaram em conta que você está usando python.

O python GIL não permite que você efetivamente use vários núcleos.

Anon
fonte
3
O GIL torna um pouco mais difícil usar todos os 4 núcleos. De maneira alguma isso torna impossível, ou mesmo realmente tão desafiador.
Fake Name
5

O uso de vários núcleos requer a exposição explícita do paralelismo no nível do encadeamento ao sistema operacional, o que geralmente exige que o programador grave um programa com vários encadeamentos . (Ou para executar um programa de thread único várias vezes em entradas diferentes, como compilar com make -j4)

Os compiladores para alguns idiomas oferecem suporte à paralelização automática. Por exemplo, C ou C ++ com OpenMP podem compilar um for()loop comum em um programa que inicia vários threads.

#pragma omp parallel for
for(int i = 0; i < 1000000; ++i)
{
   A[i] = B[i] * constant + C[i];
}

Mas ainda assim, isso precisa acontecer quando você escreve ou compila o programa. Não há como o hardware e os sistemas operacionais atuais usarem vários núcleos para acelerar um programa de thread único.


Relacionado: Como um único encadeamento é executado em vários núcleos? : resposta: eles não. Mas existem outros tipos de paralelismo, como o paralelismo no nível da instrução que um único núcleo da CPU encontra e explora para executar um único encadeamento mais rapidamente do que uma instrução por vez.

Minha resposta a essa pergunta entra em alguns detalhes de como as CPUs modernas encontram e exploram um paralelismo detalhado no nível das instruções. (Principalmente o x86). Isso é apenas parte de como as CPUs normais funcionam, tendo várias instruções em andamento ao mesmo tempo, e não é algo que você precisa habilitar especialmente. (Existem contadores de desempenho que permitem ver quantas instruções por clock sua CPU conseguiu executar durante a execução de um programa ou outras medidas.)

Observe que o RPi3 usa núcleos de CPU ARM Cortex-A53 em ordem . Cada núcleo é superescalar de 2 largos (2 instruções por relógio, conforme o ILP permite), mas não pode reordenar as instruções para encontrar mais paralelismo no nível das instruções e ocultar a latência.

Ainda assim, a CPU é canalizada, portanto, o número total de instruções em andamento (desde a busca e decodificação até o estágio de write-back no final do pipeline) é significativo. Quando as dependências de dados não limitam as coisas, pode haver 2 instruções em cada estágio do pipeline em que a CPU está trabalhando, com uma taxa de transferência de 2 instruções por relógio. (Isso é o que significa 2).

Ele não pode executar instruções fora de ordem, mas com uma ordenação cuidadosa de instruções (geralmente por um compilador), ainda pode ocultar a latência de uma instrução que leva vários ciclos para que sua saída esteja pronta. (por exemplo, uma carga, mesmo que seja atingida no cache ou em uma multiplicação, levará vários ciclos, contra uma adição estar pronta no próximo ciclo). O truque é solicitar as instruções asm para que haja várias instruções independentes entre a que produz um resultado e a que o utiliza.

Ter o software (um compilador) agendando estaticamente as instruções é mais frágil do que o hardware que pode ser reordenado internamente, preservando a ilusão de execução na ordem do programa. É muito difícil para os compiladores fazerem um trabalho tão bom quanto uma pequena janela fora de ordem para reordenar as instruções, porque as falhas no cache são imprevisíveis e é difícil analisar as cadeias de dependência nas chamadas de função em tempo de compilação. E o número de registros é limitado sem a renomeação de registros de hardware.


Tudo isso é um pequeno conforto quando o código é mais lento do que você gostaria. Certamente, há um monte de coisas legais embaixo do capô em um Cortex-A53, mas há mais coisas legais embaixo do capô em um Cortex-A57 (como execução fora de ordem de até 3 instruções por relógio) e ainda mais uma grande CPU x86 como a Skylake (sem mencionar as diferenças de velocidade do relógio).

O Cortex-A53 é fantástico, comparado a um https://en.wikipedia.org/wiki/Classic_RISC_pipeline como MIPS original que você aprenderia na aula de arquitetura de computadores, mas, pelos padrões modernos, é bastante barato.

Peter Cordes
fonte
1
"Não há como o hardware e sistemas operacionais atuais usarem múltiplos núcleos para acelerar um programa de thread único". não é rigorosamente verdade. Por exemplo, em um único programa Java encadeado, o Java pode fazer tudo o que é GC e analisar / compilar em tempo de execução em núcleos adicionais da CPU. A análise de tempo de execução é muito importante, pois ela pode decidir fazer algumas otimizações com base nos caminhos de código em execução sem custar nada ao seu "thread único" e pode acelerar muito com o que aprendeu com a análise. Em geral, embora o seu ponto seja bom.
Bill K
@ BillK Para ser justo, o "programa" nesse contexto javanão é myapp.jar, e certamente não é único.
goldilocks
1
É verdade que eu estava apenas apontando que, dependendo de como o tempo de execução foi projetado, o "código que você escreve", mesmo com thread único, pode tirar proveito de núcleos extras sem codificá-lo explicitamente como um aplicativo com vários threads. O Python também poderia fornecer um tempo de execução mais poderoso, mas seria inútil. De qualquer maneira, não é um grande salto - acho que mesmo o java usa apenas um núcleo extra de 1/2 para ajudar com um único aplicativo encadeado.
Bill K
" Não há como o hardware e os sistemas operacionais atuais usarem múltiplos núcleos para acelerar um programa de thread único " . Imediatamente depois, você explica como o hardware executa instruções em paralelo.
Thomas Weller
3
@ThomasWeller Sim, mas ser exigente no pipeline do processador não usa vários núcleos; está contido em um núcleo, mas permite trabalhar em vários fluxos de instruções. Ou seja, é uma forma de paralelismo, mas não é uma forma de rosqueamento multinúcleo.
goldilocks
4

Não é assim que as CPUs funcionam ... de jeito nenhum.

Como está atualmente, sua CPU é perfeitamente capaz de funcionar com 100% de uso, assumindo que não está sendo acelerada devido a problemas relacionados à temperatura a 80 graus Celsius ou mais. Dito isto, você geralmente não deseja ver sua CPU fixada em 100%. Se você está rotineiramente com 100% de utilização da CPU, provavelmente tem muito para o seu processador suportar. Isso causará gagueira e uma experiência do usuário geralmente infeliz.

Para comparar com algo mais físico, a utilização da CPU é muito parecida com um carro. O carro provavelmente é capaz de percorrer 160 km / h, mas há uma boa chance de seu velocímetro ler algo significativamente abaixo disso. Quando estiver na cidade, você poderá nunca conseguir cerca de 40 km / h. Isso não muda no entanto que o carro pode ir a 100 mph. Você simplesmente não pressionou o acelerador com força suficiente.

Se você simplesmente fizer o RPi fazer mais coisas (pressione mais o acelerador), você verá o valor de utilização da CPU subir. Por exemplo, observe a utilização da CPU ao executar o comando yesem uma janela do terminal (lembre-se de que ctrl+ctermina os comandos do terminal). Isso aumentará sua CPU em 25%, pois maximiza um de seus quatro núcleos de CPU.

Jacobm001
fonte
5
Eu acho que essa resposta é enganosa, onde se diz que você geralmente não quer que sua CPU seja executada com 100% de utilização. Existem muitas aplicações numericamente intensivas em que você deseja 100% de utilização porque dedicou a (s) máquina (s) ao cálculo. Para obter o tempo real do supercomputador, você geralmente precisa provar que seu código está otimizado o suficiente para fazer isso; caso contrário, eles o negarão como um desperdício de recursos. Se você possui um cluster Pi, obviamente não está obtendo desempenho supercomputador, mas isso pode tornar mais crítico maximizar o uso, e não menos!
Tijolo
3
Eu meio que concordo com Brick no sentido de que parece implícito aqui que se um processador está em 25%, é porque é para economizar gás ou obedecer ao limite de velocidade;) ou para ser educado e não monopolizar os recursos. Você pode deixar mais claro que geralmente é porque qualquer tarefa está aguardando E / S a maior parte do tempo. Coisas que podem rodar em um único núcleo até o fim. O que (idealmente) evita que isso atrapalhe a interface do usuário é reduzir o tempo - mas, realisticamente, ainda é muito fácil bloquear uma pequena máquina de núcleo único.
goldilocks
A utilização de 100% da CPU geralmente não causa UX ruim. Até 1000% pode ser bom o suficiente, pois a maioria dos programas não é limitada pela CPU, mas por outros fatores. Os únicos programas que ficam lentos devido a uma carga extrema da CPU são os programas que realmente usam a CPU o tempo todo.
Oskar Skog
4

As outras respostas fornecem bons detalhes, mas não parecem abordar suas perguntas especificamente.

  1. Sim, se o programa (e o sistema operacional) estiver programado para contabilizar vários núcleos. ('Threading' é o termo na programação aqui)
  2. A máquina usa o máximo ou o mínimo de cada núcleo necessário para concluir a tarefa. então não há necessidade de mudar nada.
  3. Você pode definir limites para o uso máximo, mas não é necessário no uso normal. consulte as respostas aqui: - /unix/151883/limiting-processes-to-not-exceed-more-than-10-of-cpu-usage

NB:

Se você deseja melhorar o desempenho geral do pi, convém examinar o Overclocking. Isso permite que a CPU seja executada em uma taxa mais rápida. As desvantagens são aumento da produção de calor, menor vida útil do processador e aumento do consumo de energia.

Stese
fonte
2

Se possível, eu parametrizaria o script e os executaria em processos Python separados. Por exemplo:

cat parameters.txt | xargs -n1 -P4 python run.py

Uma outra alternativa é a biblioteca de multiprocessamento já mencionada, que permite a junção de processos python. Mas isso também exige que você tenha uma lista de parâmetros (como um nome de arquivo) para os quais deseja que os cálculos sejam executados.

NikoNyrh
fonte
Primeira parte: Sim, presumir o problema em questão é embaraçosamente paralelo .
Peter Mortensen
É verdade que eu estava familiarizado apenas com o pool de processamento do multiprocessamento, mapmas aparentemente ele também possui muitas construções de memória compartilhada bastante sofisticadas.
NikoNyrh
1

Eu acho que o OP pode não entender completamente os conceitos de programação multi-core / multi-thread e como é difícil utilizar totalmente 100% do multi-core, a menos que o algoritmo possa ser facilmente transformado em um problema embaraçosamente paralelo .

Para mais informações, você pode ler mais sobre o conhecido título do artigo "O almoço gratuito acabou" http://www.gotw.ca/publications/concurrency-ddj.htm

sonofusion82
fonte
0

Se você deseja testar seu RPI. Você pode executar stresscomo aqui , e pode ver como suas CPUs estão sendo usadas htop. Isso é útil porque você pode ver se sua fonte de energia é suficiente, se não for suficiente, seu RPI tentará usar muita corrente (amperagem) e desligará.

Por outro lado, se você quiser usar scripts python, deverá ver o joblibque funciona melhor quando quiser paralelizar processos e, portanto, usará o número de processadores que deseja.

silgon
fonte
0

Embora todas essas respostas estejam corretas de maneiras diferentes, é verdade que o sistema operacional usará automaticamente os diferentes núcleos para distribuir a carga. Você pode ver isso com um programa python simples (temp.py, por exemplo)

while True:
  x = 1.0

abra um terminal da área de trabalho RPi e digite o $ topque mostrará o trabalho do processador. Em seguida, abra outro terminal e python3 temp.pyvocê verá um trabalho python3 aumentar para 100% do tempo do processador. Em seguida, abra outro terminal e repita o processo e veja como você se move até 400%. Então, em um nível, como o @Shadow comentou, é simples e é o padrão. No entanto, projetar programas que podem usar o processamento paralelo não é trivial, como outros explicaram.

paddyg
fonte
0

A resposta é um sim retumbante! Você simplesmente tem que escrever seu programa para reconhecê-los e usá-los. Programas que fazem isso podem usar os núcleos. Eu escrevo o meu para fazer isso em Java e, portanto, posso.

As respostas acima dos desenvolvedores de Python têm um conceito muito limitado dessa resposta e, portanto, podem ser muito confusas, mas a resposta é SIM e apenas SIM!

Orubel
fonte
Você pode por favor elaborar?
SDsolar
0

Como o OP não especificou python em sua pergunta, gostaria de sugerir mais duas linguagens modernas que funcionam bem no Raspberry Pi e têm maneiras muito fáceis de usar a simultaneidade.

Meu favorito atual é o idioma Rust. Eu escrevi e compilei programas no Pi. A ferrugem é legal, pois evita muitos tipos de erros de ponteiro e condição de corrida, o que torna a escrita de código simultâneo mais fácil e segura. O Rust é uma linguagem de programação de sistemas, mas pode fazer praticamente qualquer coisa que C possa fazer.

Outro idioma é Go (também chamado Golang para facilitar a pesquisa). O Go foi criado pela equipe do Google e é uma linguagem razoavelmente madura. É fácil criar corotinas no Go, que eles chamam de "rotinas Go".

Ambos os idiomas podem compilar código no Raspberry Pi, até no Pi Zero. No entanto, ambos podem ser compilados em um computador mais rápido, o que é bom para programas grandes.

NomadMaker
fonte