Re: [Python-es] Concurrencia, GIL y multi-núcleo

Pau Freixes pfreixes en milnou.net
Mie Jun 3 19:55:16 CEST 2009


Buenas :)

Francesc entiendo tu punto de vista y el énfasis que pones en muchos de tus
comentarios, de hecho he vivido muchas
de las cosas que comentas y estoy en lineas generales de acuerdo, pero esto
no me da razones para entender porque Python eligió los procesos como unidad
de procesamiento en paradigmas de varios núcleos. Es importante ver que
tenemos un discurso distinto en el momento de enfocar la problemàtica porque
estamos viendo las cosas des de prespectivas distintas y lo mas importante
de uso.

Mi discurso gira mas hacia el uso de la multiconcurrencia en paradigmas
cliente-servidor mientras que tu enfocas mas el discurso
en la generación de código :), aún asi sigo pensando que la
multiconcurrència tendria que ser otra herramienta mas a utilizar en
la optimización. Si tienes un problema delante vas ganando velocidad a
medida que atacas ciertas problemàticas de tu código, desde la simple
especialización hasta el uso de instrucciones vectoriales. Pero la multi
concurrència sigue teniendo un hueco [1] en ese hueco es donde yo quiero
llegar, threads vs processos. Porque Python se ha decantado por los
processos?

De todas formas aprovecho para hacer algunos comentarios de tus comentarios


>
>
> Según mi punto de vista, *sí* que es un problema de la aplicaciones en
> Python,
> ya que muchas de ellas (especialmente las que están diseñadas para
> aprovechar
> al máximo los recursos de cálculo disponibles) se programan como
> extensiones C
> (directamente o con alguna interface como Pyrex/Cython) o incluso en
> Fortran
> (a través de F2PY, por ejemplo). Y en C y Fortran sí que es relativamente
> fácil usar las capacidades de vectorización.  Y además, en C y Fortran uno
> *sí* que es capaz de librarse del bloqueo del GIL sin problemas.
>
> Respecto a la estandarización, estoy de acuerdo contigo en que es un
> problema.
> Sin embargo, hay que recordar que el conjunto SSE2 lo implementan
> *completamente* tanto Intel como AMD en todos sus procesadores desde los
> tiempos del Pemtium 4 y el Athlon.  Que haya muy poco software que lo use
> tiene muy poca justificación, desde mi punto de vista.
>

Totalmente de acuerdo con el tema de SSE2 por eso comento de que si han
habido esfuerzos :)


Te aseguro que los compiladores están todavía muy lejos de poder aprovechar
> completamente las capacidades vectoriales de los procesadores modernos,
> excepto en casos muy triviales, donde si pueden hacer una muy buena labor
> (especialmente las últimas versiones del compilador GCC, y lo digo por
> experiencia).  Curiosamente, cuando todo el mundo creia (y yo me incluyo
> entre
> ellos) que el ensamblador era una cosa obsoleta, el aprovechamiento de la
> maquinaria de vectorización por parte del programador actual pasa por
> conocer
> cosas como los registros disponibles, los ciclos de reloj de cada
> instrucción,
> los tamaños de cache, etc.  En fin, no exactamente ensamblador, pero si que
> se
> requieren unos conocimientos del hardware bastante importantes, como
> antaño.
>

Umm seguramente tenemos que llegar al uso de ensamblador, sse2 instrinsics,
o bien tener en cuenta la jerarquia de memoria. Ahora bien las actuales
versiones de GCC son capaces de optimizar mucho mas de lo que algunos pueden
esperar.


Como he dicho, el disponer de varios procesadores puede ser una solución
> válida para ciertos casos, pero no para la mayoría.  Por poner un ejemplo
> concreto, supongamos que queremos calcular la suma de dos arrays, digamos
> 'a'
> y 'b', y depositar el resultado en 'c'.  Pues bien, los procesadores
> modernos
> pueden efectuar hasta 2 sumas (y hasta 4 si se usa vectorización) en un
> mismo
> ciclo de reloj.  Sin embargo, los sistemas de memoria actuales sólo pueden
> suministrar datos a la CPU a un ritmo de 1 elemento cada entre 4 y 8 ciclos
> de
> reloj (dependiendo de la placa base).  Encima, para hacer la suma hacen
> falta
> 2 elementos, así que la CPU no tiene más remedio que quedarse parada entre
> 7 y
> 15 ciclos de reloj por cada ciclo digamos 'productivo' (estamos hablando de
> un
> factor 10 en la caida de rendimiento!).  Y en este escenario usar múltiple
> núcleos no sirve para nada, aunque si me apuras,  puede incluso llegar a
> ser
> contraproducente (por los tiempos de arbitración del bus, y por el tiempo
> empleado en sincronizar las acciones entre los distintos hilos de
> ejecución).


Umm independientemente de si son 2 o 4 ciclos - hit de cache - para algo
tenemos los procesadores segmentados y con múltiples pipelines, para evitar
que ciertas operaciones saturen a otras. Igualmente creo que esto no entra
en contradicción con la multi concurrència, este es un problema de througput
de instrucciones por ciclo a raíz del disseño de la CPU y tiempo de acceso a
memoria.


> Éste es un caso un poco distinto del que estamos hablando.  Los paradigmas
> de
> los servidores que nombras (apache, squid, postfix) son efectivos incluso
> en
> sistemas de un único núcleo.  Aquí el problema básicamente es poder dar
> respuesta rápida a una serie de peticiones (los clientes) si tener que
> esperar
> a que acaben otras que pueden ser muy pesadas (pero que hay que atender
> también).  Así que el desarrolador ha decidido usar threads (o
> multiproceso)
> para poder desentenderse de tener que programar la multitarea para atender
> cada petición.  Al dejar al sistema operativo esta responsabilidad, 1) los
> cambios de contexto se hacen más rápido y 2) es mucho más fácil de
> programar.
> Aún así, cuando hablamos de despachar los más rápido posible un millón de
> peticiones, o pones un sistema con un bus de acceso a memoria ancho y
> poderoso, o no te va servir de nada cambiar tu procesador mono-núcleo por
> uno
> de 8 vias.


Con esto no estoy de acuerdo, mediante el uso de varios hilos con varias
cpus N:M podemos mejorar substancialmente la
capacidad de atender distintas peticiones y mejorar el througput del sistema
vs sitemas 1:M o 1:1. El mundo real esta lleno de ejemplos, apache, squid,
etc.


>
> Bueno, en descargo de Jesse, él ya advierte que el ejemplo está 'trucado'
> (contrived).  Y añade que la implementación con threads es un ejemplo
> paradigmático de contención (y aquí se refiere implícitamente al GIL, según
> entiendo).


Aquí es donde quería llegar yo, es un problema latente en las actuales
implementaciones de Python. Sigo pensando que la salida hacia delante del
modulo multiprocessing es solo un apaño a corto plazo. Que passarà cuando
tengamos ordenadores con 80 processadores, y algunos de ellos especializados
?

Sin embargo, cualquiera que haya intentado elaborar un algoritmo de cálculo
> rápido de números primos sabe que hay maneras mucho más eficientes de
> hacerlo,
> sin necesidad de recurrir a funciones artificialmente 'costosas'.  Por
> ejemplo, en [1] se puede ver un caso de algoritmo que puede calcular los
> números primos entre el 1 y el *100 millones* en 13 segundos, usando un
> viejo
> Athlon 2400XP con un solo núcleo, mientras que al ejemplo de Jesse le
> cuesta 6
> minutos encontrar los primos entre el 1 millón y el 5 millones, y esto
> usando
> 8 núcleos Core2 recientes!.  Y crees que usando multiproceso con varios
> núcleos en [1] se podría mejorar la cifra? lo dudo mucho.
>

Totalmente de acuerdo, de la misma forma que la solución al problema de
pythagoras + fermat se puede hacer de forma fàcil mediante un buen algoritmo
con un speed up de 100 - si no recuerdo mal - sin tener que utilizar
multiples hilos. Pero sigo pensando
que esa no es la cuestión, quizá las distintas orientaciones/usos que
estamos viendo en la multiconcurrencia separa nuestras objeciones :)


[1] http://www.hfadeel.com/Blog/?p=135
[2] http://www.streamtech.nl/problemset/106.html

-- 
--pau
_______________________________________________
Lista de correo Python-es 
http://listas.aditel.org/listinfo/python-es
FAQ: http://listas.aditel.org/faqpyes





Más información sobre la lista de distribución Python-es