2009-04-10 13 views

Respuesta

6

Está solicitando posibles cambios en el sistema operativo, por lo que supongo que hay un equipo de ingeniería importante detrás de este esfuerzo.

También hay unas cuantas piezas de clarififying información que ayudaría a definir los parámetros del problema:

¿Cuánto IPC (comunicación entre procesos) se puede pedir?
¿Realmente tienen que ser hilos, o pueden ser procesos?
Si son procesos, ¿está bien si tienen que hablar entre ellos a través de sockets, y no mediante el uso de memoria compartida?
¿Qué es la arquitectura de la memoria? ¿Eres SMP directo con 1024 núcleos, o hay alguna otra NUMA (arquitectura de memoria no uniforme) o MMP aquí? ¿Cómo son sus tablas de páginas?

Conociendo solo la información más pequeña sobre los sistemas Azul, supongo que tiene muy poco IPC, y que un simple modelo "ejecutar un kernel por núcleo" podría funcionar muy bien. Si los procesos necesitan hablar entre ellos, entonces pueden crear conectores y transferir datos de esa manera. ¿Su hardware es compatible con este modelo? (Es probable que también necesite una dirección IP por núcleo, y en 1024 direcciones IP, esto podría ser problemático, aunque todos podrían ser NAT, y tal vez no sea tan importante). Por supuesto, este modelo daría lugar a algunas ineficiencias, como tablas de página adicionales, y un poco de sobrecarga de RAM, e incluso puede que no sea compatible con su sistema de hardware.

Incluso si "1 núcleo por núcleo" no funciona, es probable que pueda ejecutar núcleos de 1024/8, y que esté bien, permitiendo que cada kernel controle 8 CPU físicas.

Dicho esto, si quisiera ejecutar 1 hilo por núcleo en una máquina SMP tradicional con 1024 núcleos (y solo unas pocas CPU físicas), entonces esperaría que el planificador O (1) anticuado sea lo que usted querer. Es probable que su CPU [0] termine casi al 100% en kernel y en el manejo de interrupciones, pero eso está bien para este caso de uso, a menos que necesite más de 1 núcleo para manejar su carga de trabajo.

15

Programar miles de subprocesos no es un gran problema, pero sí programarlos en cientos de CPU. Lo que necesita, ante todo, es el bloqueo muy preciso o, mejor aún, estructuras de datos y algoritmos sin bloqueos. Simplemente no puede permitirse que 200 CPU esperen mientras una CPU ejecuta una sección crítica.

5

Mi conjetura sin educación sería que hay una cola de ejecución por procesador y un algoritmo de robo de trabajo cuando un procesador está inactivo. Pude ver que esto funciona en un modelo M: N, donde hay un solo proceso por CPU y procesos livianos como elementos de trabajo. Esto se sentiría similar a un grupo de subprocesos de robo de trabajo, como el de la biblioteca fork-join de Java-7.

Si realmente quieres saber, ve a Solaris Internals o explora el código del kernel de Solaris. Todavía estoy leyendo Design & Impl de FreeBSD, con Solaris Internals siendo el próximo en mi lista, así que todo lo que puedo hacer es hacer locas conjeturas atm.

1

Estoy bastante seguro de que el SGI Altix que tenemos en el trabajo, (que hace ccNUMA) utiliza hardware especial para la coherencia de la memoria caché.

Hay una enorme sobrecarga conectada para mantener 4 MB de caché por núcleo coherente. Es poco probable que suceda solo en el software.

en una matriz de 256 cpus necesitaría 768mb de memoria RAM solo para mantener los bits de invalidación de caché. caché de 12 MB/128 bytes por línea de caché * 256² núcleos.

+0

Sí, las máquinas Altix tienen el llamado "directorio distribuido" CC. – janneb

1

La modificación del sistema operativo es una cosa, pero el uso del código de la aplicación sin cambios es una pérdida de hardware. Al superar un límite (dependiendo del hardware), el esfuerzo por mantener la coherencia y la sincronización para ejecutar código genérico es demasiado. Puedes hacerlo, pero será muy caro. Desde el lado del sistema operativo necesitarás un modelo de afinidad complejo, es decir, no saltar las CPU solo porque la tuya está ocupada. Programación de subprocesos según la topología de hardware: colaboración de subprocesos en las CPU que están "cerca" para minimizar las penalizaciones. El robo de trabajo simple no es una buena solución, debe considerar la topología. Una solución es el robo de trabajo jerárquico: robar el trabajo por distancia, dividir la topología en sectores e intentar robar desde el más cercano primero. tocando un poco el problema de bloqueo; todavía usarás spin-locks nd, pero usando implementaciones totalmente diferentes. Este es probablemente el campo más patentado en CS en estos días. Pero, nuevamente, deberá programar específicamente para una escala tan masiva. O simplemente lo subutilizarás. No hay "paralelizadores" automáticos que lo hagan por usted.

6

Hacer escala en Linux ha sido un proyecto largo y continuo. El primer kernel de Linux con capacidad de multiprocesador tenía un único bloqueo que protegía todo el kernel (Big Kernel Lock, BKL), que era simple, pero con escalabilidad limitada.

Posteriormente, el bloqueo se ha hecho de grano más fino, es decir, hay muchos bloqueos (¿miles?), Cada uno de los cuales cubre solo una pequeña porción de datos. Sin embargo, existen límites de hasta qué punto esto puede tomarse, ya que el bloqueo detallado tiende a ser complicado y el bloqueo comienza a consumir el beneficio de rendimiento, especialmente considerando que la mayoría de los sistemas Linux multi-CPU tienen relativamente pocas CPU.

Otra cosa es que, en la medida de lo posible, el kernel usa estructuras de datos por CPU. Esto es muy importante, ya que evita los problemas de rendimiento de coherencia de caché con datos compartidos y, por supuesto, no hay gastos generales de bloqueo. P.ej. cada CPU ejecuta su propio planificador de procesos, requiriendo solo sincronización global ocasional.

Además, algunos algoritmos se eligen teniendo en cuenta la escalabilidad. P.ej. algunos datos de lectura mayoritaria están protegidos por Read-Copy-Update (RCU) en lugar de mutexes tradicionales; esto permite a los lectores proceder durante una actualización simultánea.

En cuanto a la memoria, Linux trata de asignar memoria desde el mismo nodo NUMA donde se ejecuta el proceso. Esto proporciona un mejor ancho de banda de memoria y latencia para las aplicaciones.

+0

Hay cientos de miles de bloqueos. Las estructuras de datos de inodo y dnode contienen cada uno un bloqueo por separado. Está bien. Los bloqueos desbloqueados o bloqueados y no esperados solo consumen unos pocos bytes de RAM y ningún otro recurso. – Joshua

1

La forma más fácil de hacerlo es vincular cada proceso/subproceso a unos pocos CPUS, y solo esas CPU tendrían que competir por un bloqueo en ese subproceso. Obviamente, debería haber alguna manera de mover los hilos para equilibrar la carga, pero en una arquitectura NUMA, debe minimizar esto tanto como sea posible.

0

Incluso en sistemas Intel de doble núcleo, estoy bastante seguro de que Linux ya puede manejar "miles" de hilos con subprocesos posix nativos.

(Glibc y el kernel deben configurarse para admitir esto, sin embargo, creo que la mayoría de los sistemas actualmente lo tienen de forma predeterminada).

Cuestiones relacionadas