¿Puedo usar los 4 núcleos de la CPU de la Raspberry Pi?

11

Me preguntaba si hay una manera simple de "encender" todo el 100% de la CPU para que pueda ejecutar procesos más rápido (como los cálculos de Python).

1) ¿Es esto posible?

2) ¿Hay alguna manera fácil de volver a la normalidad?

3) ¿Hay alguna manera de usar menos CPU si lo desea?

Estoy pensando en una interacción de línea de comando como:

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

Yaya
fuente
1
La respuesta corta es No
Steve Robillard
16
La respuesta larga es "Si fuera así de simple, sería el valor predeterminado"
Sombra
18
Ambos de sus comentarios son engañosas y podría implicar que el Pi tiene 4 núcleos pero sólo utiliza nunca 1. Una mejor respuesta es que los cuatro núcleos SON ya está encendido, pero que Python (y cualquier otro programa, para el caso) sólo se utilizará más de 1 núcleo a menos que sean multiproceso. Python aún puede bloquearse de manera efectiva utilizando un solo núcleo, incluso con subprocesos múltiples debido al bloqueo global del intérprete, pero eso está un poco más allá del alcance de esta pregunta.
Sohcahtoa82
13
Para aclarar, creo que el OP tiene un malentendido sobre cómo funcionan las CPU multinúcleo, y sus respuestas solo refuerzan su malentendido.
Sohcahtoa82
66
La forma más fácil de hacer que un programa Python sea más rápido es reescribir en un lenguaje compilado (o al menos hacer que las tareas críticas usen el módulo ac).
Milliways

Respuestas:

21

Por defecto, cualquier computadora intentará usar todos sus núcleos cuando pueda. Sin embargo, solo puede lograr esto cuando una aplicación es multiproceso. Si no lo es (es decir, un script de Python que no usa el threadingmódulo), entonces solo puede usar, como máximo, un núcleo. Esto equivale al 25% de la CPU en una CPU de cuatro núcleos. Si desea modificar su secuencia de comandos para usar múltiples núcleos, puede dividir su cálculo en varias partes y realizar varios subprocesos como se muestra en la documentación de Python .

Actualizar:

Como respondió Anon , esto no funcionará sin trabajar con GIL (Global Interpreter Lock) de Python. Esto permite que las tareas funcionen (aparentemente) al mismo tiempo, pero no permite que el código se ejecute en múltiples núcleos. Si está utilizando módulos escritos en C (por ejemplo, numpy), pueden permitirle usar múltiples núcleos para superar esa limitación. Además, si esa no es una opción, Python ofrece multiprocesamiento , que le permite ejecutar cualquier tarea en múltiples núcleos.

lights0123
fuente
La actualización, que es correcta, explica por qué la primera parte de la respuesta es incorrecta con respecto a Python. Solo evita esta limitación de Python escribiendo módulos C o algún lenguaje compilado, en cuyo punto ya no está escribiendo Python. Si el rendimiento es crítico, ir a un lenguaje compilado es la respuesta correcta. (Multiprocesamiento es no lo mismo desde el punto de vista del uso de recursos.)
Ladrillo
44
@Brick Solo para que quede claro, un lenguaje compilado ciertamente no es un requisito para un multiproceso adecuado en el proceso. Demonios, incluso el GIL de Python es un detalle de implementación (concedido, para el popular CPython): hay otros intérpretes de Python que estarán felices de multiprocesar, por ejemplo, Jython y IronPython.
Bob
44
Además de la confusión, Python se compila; en el caso de CPython, se compila en el bytecode de CPython que se ejecuta en la VM de CPython. Para Jython, se compila en código de bytes Java que se ejecuta en la JVM. Y finalmente, IronPython compila a CIL, que se dirige al tiempo de ejecución .NET. Entonces, "ir a un lenguaje compilado" para el rendimiento realmente no tiene sentido;)
marcelm
cualquier computadora intentará usar todos sus núcleos cuando pueda. En realidad no, solo usará todos sus núcleos (o hará cualquier otra cosa) cuando se le indique . Esa distinción puede parecer obvia o incluso condescendiente para los experimentados, pero parece que el OP necesita apreciar que no sucede automáticamente.
nekomatic
13

Me preguntaba si hay una manera simple de "encender" todo el 100% de la CPU para que pueda ejecutar procesos más rápido (como los cálculos de Python).

No en el sentido de que creo que estás insinuando. Este no es un problema específico de pi, tampoco, es una restricción lógica.

Por sí mismas, las computadoras actualmente no tienen mucha capacidad para determinar que un proceso que se ejecuta como un solo subproceso puede ejecutarse en paralelo. Tenga en cuenta que en el momento en que podrían tener esta capacidad, no habría necesidad de programadores informáticos, porque un sistema informático que podría hacer esto también podría escribir su propio código 1 ..

Considere la siguiente expresión matemática simple:

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

Existe cierto potencial para que esto se calcule en paralelo, pero es lógicamente limitado. Yo diría que no tiene sentido en más de dos hilos, e incluso en su mayoría solo será uno:

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

El hilo # 2 ha contribuido calculando 3 + 6 = 9, usado en el paso C por el hilo # 1, guardándolo en un paso. Pero eso es lo más lejos que llegará el paralelismo útil. Mientras que el hilo # 2 podría calcular 17/9 mientras que el # 1 está haciendo 6 * 17, hacerlo sería inútil, porque ahora tiene dos caminos diferentes hacia el mismo objetivo que no pueden ser recombinados. Es decir, el # 2 podría seguir funcionando:

b) 17 / 9 c) 1.888 * 6

Y terminan con el mismo resultado que el hilo # 1 (11.333), pero no se han ayudado entre sí más allá del paso A, por lo tanto, hacer que dos de ellos persigan este objetivo es una pérdida de tiempo.

(Tenga en cuenta que este ejemplo no es literal; tiene la intención de demostrar un principio lógico. La escala en la que se enhebran las tareas en el código de usuario es mucho mayor, pero no necesita una verdadera lección en programación de subprocesos múltiples para capta la idea aquí.)

La explotación de múltiples procesadores requiere un código escrito para hacerlo. No puedes simplemente tomar nada y decir: "¡oh, usa los 4 núcleos y hazlo más rápido!". Eso no es lo que sucedería. Lógicamente, muchos (... o la mayoría) de los problemas y tareas implican pasos que no pueden suceder en paralelo, deben suceder en secuencia.


1. Pero vea el comentario de Felix Dombek a continuación; No soy un experto en IA. También vale la pena señalar que, según los comentarios de Peter Corde, los sistemas de instrucción y procesadores contemporáneos pueden ser explotados por el sistema operativo para optimizar cosas muy finas de forma paralela, y las tuberías de hardware también lo hacen, aunque no entre núcleos (un solo core tiene más de una cosa en funcionamiento, operando en la secuencia de instrucciones en varios puntos antes de su ejecución final). Estaba tratando de seguir el tema de los hilos de los usuarios aquí, ya que creo que eso es más o menos a lo que te estás refiriendo.

Ricitos de oro
fuente
44
He escrito mucho código numérico paralelo, y esto es un poco engañoso en cuanto a los detalles. No se paraleliza al nivel de operaciones aritméticas individuales como esta. (Si nos expandimos más allá de Raspberry Pi, algunos compiladores y procesadores ya paralelizarán algo de eso, incluso fuera de las estructuras de subprocesamiento de todos modos). Paralelamente tareas enteras en trozos más grandes.
Brick
44
@Brick "No se paraleliza al nivel de operaciones aritméticas individuales como esta". -> Por supuesto que no, pero haré más explícito que esto es una analogía, no una lección sobre programación multihilo.
Ricitos de oro
44
El paralelismo en el cálculo que utiliza como ejemplo está tan localizado que creará paralelismo a nivel de instrucción en un programa que lo calcula, y las CPU con ejecución fuera de orden pueden explotar ese paralelismo por sí mismos.
Peter Cordes
2
RPi3 usa un superescalar de 2 anchos en orden en.wikipedia.org/wiki/ARM_Cortex-A53 , por lo que con una cuidadosa programación, un compilador aún puede explotar el ILP poniendo dos addinstrucciones una al lado de la otra para que ambos puedan ejecutarse en el mismo ciclo de reloj Sin embargo, el siguiente resto de multiplicación y división se serializará por dependencias de datos, como usted señala.
Peter Cordes
1
La determinación de partes paralelizables no requiere necesariamente una IA fuerte. En el sentido "general", podría; pero es fácilmente imaginable que las computadoras podrían usar un enfoque heurístico que funciona principalmente en muchos casos prácticos. Como, una computadora no probó el último teorema de Fermat, pero ciertamente hay programas de prueba de teoremas. Tenga en cuenta que los compiladores modernos para lenguajes de programación ya hacen muchos reordenamientos de código como parte de sus pasos de optimización, lo que implica razonar sobre partes paralelizables.
Felix Dombek
7

No para python.

Otras personas le sugieren que estudie los subprocesos, que es una respuesta válida para la mayoría de los idiomas, pero no tuvieron en cuenta que está utilizando python.

Python GIL no le permite hacer uso efectivo de múltiples núcleos.

Luego
fuente
3
El GIL hace que sea un poco más difícil usar los 4 núcleos. De ninguna manera lo hace imposible, o incluso realmente tan desafiante.
Nombre falso el
5

El uso de múltiples núcleos requiere exponer explícitamente el paralelismo de nivel de subproceso al sistema operativo, que generalmente requiere que el programador escriba un programa de subprocesos múltiples. (O para ejecutar un programa de subproceso único varias veces en diferentes entradas, como compilar con make -j4)

Sin embargo, los compiladores para algunos idiomas admiten la paralelización automática. Por ejemplo, C o C ++ con OpenMP puede compilar un for()bucle ordinario en un programa que inicia múltiples subprocesos.

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

Pero aún así, esto tiene que suceder cuando escribió o compiló el programa. No hay forma de que el hardware y los sistemas operativos actuales usen múltiples núcleos para acelerar un programa de subproceso único.


Relacionado: ¿Cómo se ejecuta un solo hilo en múltiples núcleos? : respuesta: no lo hacen. Pero hay otros tipos de paralelismo, como el paralelismo de nivel de instrucción que un solo núcleo de CPU encuentra y explota para ejecutar un solo hilo más rápido que una instrucción a la vez.

Mi respuesta a esa pregunta entra en algunos de los detalles de cómo las CPU modernas encuentran y explotan el paralelismo de nivel de instrucción de grano fino. (Principalmente centrado en x86). Eso es solo parte de cómo funcionan las CPU normales, al tener varias instrucciones en vuelo a la vez, y no es algo que necesite habilitar especialmente. (Sin embargo, hay contadores de rendimiento que le permiten ver cuántas instrucciones por reloj logró ejecutar su CPU mientras ejecutaba un programa u otras medidas).

Tenga en cuenta que RPi3 utiliza núcleos de CPU ARM Cortex-A53 en orden . Cada núcleo es superescalar de ancho 2 (2 instrucciones por reloj como lo permite ILP), pero no puede reordenar las instrucciones para encontrar más paralelismo a nivel de instrucción y ocultar latencia.

Aún así, la CPU está canalizada, por lo que el número total de instrucciones en vuelo (desde recuperar y decodificar hasta la etapa de reescritura al final de la canalización) es significativo. Cuando las dependencias de datos no limitan las cosas, puede haber 2 instrucciones en cada etapa de canalización en las que la CPU está trabajando, con un rendimiento de 2 instrucciones por reloj. (Eso es lo que significa 2 ancho).

No puede ejecutar instrucciones fuera de orden, pero con un orden de instrucciones cuidadoso (generalmente por un compilador) aún puede ocultar la latencia de una instrucción que toma varios ciclos para que su salida esté lista. (por ejemplo, una carga incluso si llega a la memoria caché o una multiplicación tomará varios ciclos, en comparación con una adición que esté lista el próximo ciclo). El truco consiste en ordenar las instrucciones asm para que haya múltiples instrucciones independientes entre la que produce un resultado y la que lo utiliza.

Tener software (un compilador) para programar las instrucciones estáticamente es más frágil que tener hardware que puede reordenarse internamente mientras se preserva la ilusión de ejecutarse en orden de programa. Es muy difícil para los compiladores hacer un trabajo tan bueno como incluso una pequeña ventana fuera de orden para reordenar las instrucciones porque los errores de caché son impredecibles, y es difícil analizar las cadenas de dependencia a través de las llamadas a funciones en tiempo de compilación. Y el número de registros es limitado sin cambiar el nombre del registro de hardware.


Todo esto es una pequeña comodidad cuando su código se ejecuta más lentamente de lo que desea. Claro que hay muchas cosas interesantes debajo del capó en un Cortex-A53, pero hay más cosas geniales debajo del capó en un Cortex-A57 (como la ejecución fuera de orden de hasta 3 instrucciones por reloj), e incluso más en una gran CPU x86 como Skylake (sin mencionar las diferencias de velocidad de reloj).

Cortex-A53 es bastante fantástico en comparación con un https://en.wikipedia.org/wiki/Classic_RISC_pipeline como MIPS original sobre el que aprendería en la clase de arquitectura de computadora, pero según los estándares modernos es bastante bajo.

Peter Cordes
fuente
1
"No hay forma de que el hardware y los sistemas operativos actuales usen múltiples núcleos para acelerar un programa de subproceso único". No es estrictamente cierto. Por ejemplo, en un programa Java de un solo subproceso, Java puede hacer todo su análisis de GC y análisis / compilación en tiempo de ejecución en núcleos de CPU adicionales. El análisis de tiempo de ejecución es un gran problema porque puede decidir hacer algunas optimizaciones basadas en la ejecución de rutas de código sin costarle nada a su "hilo único" y puede acelerarlo enormemente con lo que aprende del análisis. En general, aunque su punto es bueno.
Bill K
@BillK Para ser justos, el "programa" en ese contexto javano lo es myapp.jar, y ciertamente no es de un solo subproceso.
Ricitos de oro
1
Es cierto, solo estaba señalando que, dependiendo de cómo se diseñó el tiempo de ejecución, el "código que escribe", aunque sea de un solo subproceso, puede aprovechar núcleos adicionales sin codificarlo explícitamente como una aplicación de subprocesos múltiples. Python también podría proporcionar un tiempo de ejecución más potente, pero sería inútil. De todos modos, no es un gran salto: creo que incluso Java solo usa como 1/2 núcleo adicional para ayudar con una sola aplicación roscada.
Bill K
" No hay forma de que el hardware y los sistemas operativos actuales usen múltiples núcleos para acelerar un programa de subproceso único " e inmediatamente después de eso, explica cómo el hardware ejecuta las instrucciones en paralelo.
Thomas Weller el
3
@ThomasWeller Sí, pero para ser selectivo, la canalización del procesador no utiliza múltiples núcleos; Está contenido en un núcleo, pero permite trabajar en múltiples flujos de instrucciones. Es decir, es una forma de paralelismo, pero no es una forma de subprocesamiento multinúcleo.
Ricitos de oro
4

Así no es como funcionan las CPU ... en absoluto.

Tal como está actualmente, su CPU es perfectamente capaz de funcionar al 100% de uso, suponiendo que no se está acelerando debido a problemas relacionados con la temperatura a 80 grados Celsius o más. Dicho esto, no (en general) desea ver su CPU vinculada al 100%. Si habitualmente utiliza el 100% de la CPU, es probable que tenga demasiado para su procesador. Esto causará tartamudeo y una experiencia de usuario generalmente infeliz.

Para comparar con algo más físico, la utilización de su CPU se parece mucho a un automóvil. Es probable que el automóvil sea capaz de avanzar 100 mph, pero hay una buena probabilidad de que su velocímetro lea algo significativamente debajo de eso. Cuando estés en la ciudad, es posible que nunca puedas alcanzar las 25 mph. Sin embargo, eso no cambia que el automóvil pueda ir a 100 mph. Simplemente no has presionado el acelerador lo suficientemente fuerte.

Si simplemente hace que el RPi haga más cosas (presione más en el acelerador), verá que la cifra de utilización de la CPU aumenta. Por ejemplo, observe la utilización de la CPU cuando ejecuta el comando yesen una ventana de terminal (recuerde que ctrl+cfinaliza los comandos de terminal). Esto aumentará su CPU en un 25%, ya que maximiza uno de sus cuatro núcleos de CPU.

Jacobm001
fuente
55
Creo que esta respuesta es engañosa cuando se dice que generalmente no desea que su CPU se ejecute al 100% de utilización. Hay muchas aplicaciones numéricamente intensivas en las que absolutamente desea una utilización del 100% porque ha dedicado la máquina (o máquinas) al cálculo. Para obtener el verdadero tiempo de la supercomputadora, a menudo tiene que demostrar que su código está optimizado lo suficientemente bien como para hacerlo, de lo contrario lo negarán como un desperdicio de recursos. Si tiene un clúster de Pi, obviamente no está obteniendo un rendimiento excelente de la computadora, pero eso podría hacer que sea más crítico maximizar el uso, ¡no menos!
Ladrillo
3
Estoy de acuerdo con Brick en el sentido de que parece implícito aquí que si un procesador está al 25%, es porque es para conservar gas u obedecer el límite de velocidad;) o para ser cortés y no acaparar recursos. Es posible que desee aclarar que generalmente es porque cualquier tarea está esperando E / S la mayor parte del tiempo. Las cosas que pueden ejecutar un solo núcleo hasta arriba lo harán. Lo que (idealmente) evita que esto interrumpa la interfaz de usuario es la reducción de tiempo, pero de manera realista, todavía es bastante fácil atascar una máquina pequeña de un solo núcleo.
Ricitos de oro
La utilización del 100% de la CPU generalmente no causa una mala experiencia de usuario. Incluso el 1000% puede ser lo suficientemente bueno, ya que la mayoría de los programas no están limitados por la CPU sino por otros factores. Los únicos programas que se vuelven lentos debido a una carga extrema de la CPU son los programas que realmente usan la CPU todo el tiempo.
Oskar Skog
4

Las otras respuestas dan buenos detalles, pero no parecen abordar sus preguntas específicamente.

  1. Sí, si el programa (y el sistema operativo) están programados para dar cuenta de múltiples núcleos. ('Threading' es el término en programación aquí)
  2. La máquina usa tanto o tan poco de cada núcleo como sea necesario para completar la tarea. así que no hay necesidad de cambiar nada.
  3. Usted puede establecer límites sobre el uso máximo, pero no hay necesidad de un uso normal. Eche un vistazo a las respuestas aquí: - /unix/151883/limiting-processes-to-not-exceed-more-than-10-of-cpu-usage

NB:

Si está buscando mejorar el rendimiento del pi en general, es posible que desee considerar Overclocking. Esto permite que la CPU funcione a un ritmo más rápido. Las desventajas son una mayor producción de calor, una menor vida útil del procesador y un mayor consumo de energía.

Stese
fuente
2

Si es posible, parametrizaría el script y los ejecutaría en procesos separados de Python. Por ejemplo:

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

Otra alternativa es la biblioteca de multiprocesamiento ya mencionada, que le permite bifurcar y unir procesos de Python. Pero eso también requiere que tenga una lista de parámetros (como un nombre de archivo) para los que desea que se ejecuten los cálculos.

NikoNyrh
fuente
Primera parte: Sí, suponiendo que el problema en cuestión es vergonzosamente paralelo .
Peter Mortensen el
Ahaa cierto, estaba familiarizado solo con el grupo de procesamiento de multiprocesamiento, mappero aparentemente también tiene muchas construcciones de memoria compartida bastante sofisticadas.
NikoNyrh
1

Creo que OP podría no comprender completamente los conceptos de programación multi-core / multi-thread y cuán difícil es utilizar completamente el 100% de multi-core a menos que el algoritmo pueda convertirse fácilmente en un problema embarazosamente paralelo .

Para obtener más información, puede leer más sobre el conocido título del artículo "Se acabó el almuerzo gratis" http://www.gotw.ca/publications/concurrency-ddj.htm

sonofusion82
fuente
0

Si quieres probar tu RPI. Puede ejecutar stresscomo aquí , luego puede ver cómo se utilizan sus CPU htop. Esto es útil porque puede ver si su fuente de energía es suficiente, si no es suficiente, su RPI intentará usar demasiada corriente (amperaje) y se apagará.

Por otro lado, si desea utilizar secuencias de comandos de Python, debería ver joblibqué funciona muy bien cuando desea paralelizar procesos, y por lo tanto utilizará la cantidad de procesadores que desee.

silgon
fuente
0

Aunque todas estas respuestas son correctas de diferentes maneras, es cierto que el sistema operativo utilizará automáticamente los diferentes núcleos para distribuir la carga. Puede ver esto con un simple programa de Python (temp.py say)

while True:
  x = 1.0

abra una terminal desde su escritorio RPi y escriba $ toplo que mostrará el trabajo del procesador. Luego abra otra terminal y python3 temp.pyverá que un trabajo de python3 aumenta al 100% del tiempo de procesador. Luego abra otra terminal y repita el proceso y vea cómo se mueve hasta el 400%. Entonces, en un nivel como comentó @Shadow, es así de simple y es el valor predeterminado. Sin embargo, el diseño de programas que pueden usar el procesamiento paralelo no es trivial como otros han explicado.

paddyg
fuente
0

¡La respuesta es un sí rotundo! Simplemente tiene que escribir su programa para reconocerlos y usarlos. Los programas que hacen esto pueden usar los núcleos. Escribo el mío para hacer esto en Java y así puedo.

Las respuestas anteriores de los desarrolladores de Python tienen un concepto muy limitado de esta respuesta, por lo que pueden ser muy confusas, ¡pero la respuesta es SÍ y solo SÍ!

Orubel
fuente
¿Puedes por favor elaborar?
SDsolar
0

Dado que el OP no especificó Python en su pregunta, me gustaría sugerir dos lenguajes modernos más que funcionen bien en la Raspberry Pi y que tengan formas muy fáciles de usar la concurrencia.

Mi favorito actual es el lenguaje Rust. He escrito y compilado programas en el Pi. Rust es bueno porque evita muchos tipos de errores de puntero y condición de carrera, lo que hace que escribir código concurrente sea más fácil y seguro. Rust es un lenguaje de programación de sistemas, pero puede hacer casi cualquier cosa que C pueda hacer.

Otro lenguaje de este tipo es Go (también llamado Golang para facilitar la búsqueda). Go fue creado por el equipo de Google y es un lenguaje razonablemente maduro. Es fácil hacer corutinas en Go, a las que llaman "rutinas Go".

Ambos lenguajes pueden compilar código en Raspberry Pi, incluso el Pi Zero. Sin embargo, ambos se pueden compilar en forma cruzada desde una computadora más rápida, lo cual es bueno para programas grandes.

NomadMaker
fuente