Los procesadores obtienen cada vez más núcleos en estos días, lo que me deja preguntándome ...
¿Deberíamos nosotros, los programadores, adaptarnos a este comportamiento y dedicar más esfuerzo a la programación de múltiples núcleos?
¿Hasta qué punto debemos hacer y optimizar esto? ¿Hilo? ¿Afinidad? Optimizaciones de hardware? ¿Algo más?
fuente
Soy un programador .NET, y sé que .NET tiene una abstracción de alto nivel para subprocesos múltiples llamada Tasks. Le protege de tener que saber demasiado sobre cómo hacer un multiproceso adecuado contra el metal. Supongo que otras plataformas de desarrollo actuales tienen abstracciones similares. Entonces, si vas a hacer algo con subprocesos múltiples, trataría de trabajar a ese nivel si es posible.
Ahora, a la pregunta de si debería preocuparse por el subprocesamiento múltiple en su aplicación particular. La respuesta a esa pregunta depende mucho de la aplicación que esté escribiendo. Si está escribiendo una aplicación que procesa en miles (o más) cosas independientes, y este procesamiento se puede hacer en paralelo, entonces seguramente obtendrá una ventaja de subprocesamiento múltiple. Sin embargo, si está escribiendo una pantalla de entrada de datos simple, el subproceso múltiple podría no comprarle mucho.
Como mínimo, debe preocuparse por el subprocesamiento múltiple cuando trabaja en una interfaz de usuario. No desea activar una operación de larga duración desde la interfaz de usuario y dejar que no responda porque secuestró el hilo de la interfaz de usuario para realizar esa operación. Encienda un hilo de fondo, y al menos dé al usuario un botón Cancelar para que no tenga que esperar a que se complete si cometió un error.
fuente
En la tierra de Objective-C y Mac OS X e iOS, los marcos (como muchos otros) están escritos para aprovechar estos aumentos en los núcleos de procesador y presentar al desarrollador una interfaz agradable para usarlos.
Ejemplo en Mac OS X e iOS es el envío de Grand Central. Hay adiciones a
libc
(creo) para facilitar el subprocesamiento múltiple basado en colas. Luego, los marcos Cocoa y Foundation (entre otros) se escriben sobre GCD, lo que le da al desarrollador un acceso fácil a las colas de despacho y al enhebrado con muy poco código de placa de caldera.Muchos lenguajes y marcos tienen conceptos similares.
fuente
La parte difícil es dividir el algoritmo intensivo de su CPU en fragmentos de ejecución que podrían enhebrarse.
Entonces, un hilo que salta continuamente de un núcleo a otro tendrá penalizaciones de rendimiento (debido a la caché de CPU de primer y segundo nivel perdida), especialmente en arquitecturas donde se emplean dos dados físicos distintos. En este caso, la afinidad de núcleo de hilo es algo bueno.
fuente
Estamos ahora (octubre de 2010) en un momento de inmensa transición.
Hoy podríamos comprar una computadora de escritorio de 12 núcleos.
Hoy podríamos comprar una tarjeta de procesamiento de 448 núcleos (busque NVidia Tesla).
Hay límites en cuanto a cuánto podemos trabajar los desarrolladores ignorando los entornos tremendamente paralelos dentro de los cuales trabajarán nuestros programas en el futuro cercano.
Los sistemas operativos, los entornos de tiempo de ejecución y las bibliotecas de programación solo pueden hacer mucho.
En el futuro, tendremos que dividir nuestro procesamiento en fragmentos discretos para un procesamiento independiente, utilizando abstracciones como el nuevo .NET Framework de tareas.
Los detalles como la gestión de caché y la afinidad seguirán presentes, pero serán la evidencia de la aplicación de alto rendimiento solamente. Ningún mismo desarrollador querrá administrar estos detalles manualmente en una máquina de 10k núcleos.
fuente
bueno, realmente depende de lo que estés desarrollando. la respuesta, dependiendo de lo que esté desarrollando, puede variar de "es insignificante" a "es absolutamente crítico, y esperamos que todos en el equipo tengan una buena comprensión y uso de implementaciones paralelas".
En la mayoría de los casos, un buen entendimiento y uso de bloqueos, subprocesos y tareas y grupos de tareas será un buen comienzo cuando se requiera paralelismo. (varía según lang / lib)
Agregue a eso las diferencias en los diseños que debe hacer: para el multiprocesamiento no trivial, a menudo uno debe aprender varios nuevos modelos de programación o estrategias de paralelización. en ese caso, el tiempo para aprender, fallar suficientes veces para tener una comprensión sólida y actualizar los programas existentes puede llevar un equipo por año (o más). una vez que haya llegado a ese punto, (¡con suerte!) no percibirá ni abordará los problemas / implementaciones como lo hace hoy (siempre que aún no haya hecho esa transición).
Otro obstáculo es que está optimizando efectivamente un programa para una determinada ejecución. Si no se le da mucho tiempo para optimizar los programas, realmente no se beneficiará tanto como debería. La paralelización de alto nivel (u obvia) puede mejorar la velocidad percibida de su programa con bastante poco esfuerzo, y eso es lo que muchos equipos llegarán hoy: "Hemos paralelizado las partes realmente obvias de la aplicación", eso está bien en algunos casos. ¿Será el beneficio de tomar la fruta baja y usar paralización simple ser proporcional al número de núcleos? a menudo, cuando hay dos o cuatro núcleos lógicos pero no tan a menudo más allá de eso. En muchos casos, es un rendimiento aceptable, dada la inversión de tiempo. Este modelo paralelo es la introducción de muchas personas para implementar buenos usos del paralelismo.
lo que aprenda usando estos modelos paralelos triviales no será ideal en todos los escenarios paralelos complejos; La aplicación efectiva de diseños paralelos complejos requiere una comprensión y un enfoque muy diferentes. Estos modelos simples a menudo están separados o tienen una interacción trivial con otros componentes del sistema. Además, muchas implementaciones de estos modelos triviales no se adaptan bien a sistemas paralelos complejos de manera efectiva: un diseño paralelo complejo malo puede tardar tanto tiempo en ejecutarse como el modelo simple. ill: se ejecuta dos veces más rápido que el modelo de subproceso único, mientras utiliza 8 núcleos lógicos durante la ejecución. Los ejemplos más comunes son usar / crear demasiados hilos y altos niveles de interferencia de sincronización. en general, esto se denomina desaceleración paralela. es bastante fácil de encontrar si aborda todos los problemas paralelos como problemas simples.
entonces, digamos que realmente debería utilizar el multihilo eficiente en sus programas (la minoría, en el clima de hoy): deberá emplear el modelo simple de manera efectiva para aprender el modelo complejo y luego volver a aprender cómo aborda el flujo y la interacción del programa. el modelo complejo es donde debería estar su programa en última instancia, ya que allí es donde está el hardware hoy y donde se realizarán las mejoras más dominantes.
La ejecución de modelos simples se puede imaginar como una bifurcación, y los modelos complejos funcionan como un ecosistema complejo. Creo que la comprensión de modelos simples, incluido el bloqueo general y el subprocesamiento, debería ser o se esperará de los desarrolladores intermedios cuando el dominio (en el que se desarrolla) lo use. comprender modelos complejos todavía es un poco inusual hoy (en la mayoría de los dominios), pero creo que la demanda aumentará bastante rápido. Como desarrolladores, muchos más de nuestros programas deberían admitir estos modelos, y la mayoría de los usos están bastante atrasados en la comprensión e implementación de estos conceptos. Dado que los recuentos de procesadores lógicos son una de las áreas más importantes de mejora de hardware, seguramente aumentará la demanda de personas que entiendan y puedan implementar sistemas complejos.
Finalmente, hay muchas personas que piensan que la solución es simplemente "agregar paralelización". a menudo, es mejor acelerar la implementación existente. Es mucho más fácil y mucho más sencillo en muchos casos. muchos programas en la naturaleza nunca han sido optimizados; Algunas personas simplemente tuvieron la impresión de que la versión no optimizada sería eclipsada por el hardware algún día pronto. mejorar el diseño o los algos de los programas existentes también es una habilidad importante si el rendimiento es importante: arrojar más núcleos a los problemas no es necesariamente la mejor o más simple solución.
Al apuntar a las PC modernas, la mayoría de nosotros que necesitamos implementar buenos sistemas paralelos no necesitaremos ir más allá de múltiples subprocesos, bloqueos, bibliotecas paralelas, un libro de lectura, y mucha experiencia escribiendo y probando programas (básicamente, reestructurando significativamente cómo programas de escritura de aproximación).
fuente
Lo hacemos, pero escribimos software pesado de cálculo para que nos beneficiemos directamente de múltiples núcleos.
A veces, el planificador mueve mucho los hilos entre núcleos. Si eso no es aceptable, puedes jugar con la afinidad central.
fuente
Tal como están las cosas, la frecuencia del procesador no aumentará en el futuro cercano. Estamos atrapados alrededor de la marca de 3 GHz (sin overclocking). Ciertamente, para muchas aplicaciones puede que no sea necesario ir más allá del multihilo muy básico. Obviamente, si está creando una aplicación de interfaz de usuario, cualquier procesamiento intensivo debe realizarse en un hilo de fondo.
Si está creando una aplicación que está procesando grandes cantidades de datos que deben ser en tiempo real, entonces sí, probablemente debería considerar la programación de subprocesos múltiples.
Para la programación de subprocesos múltiples, encontrará que obtendrá rendimientos decrecientes en su rendimiento; puede pasar horas y mejorar el programa en un 15%, y luego pasar otra semana y solo mejorarlo en un 5% adicional.
fuente