c++ shared-memory mpi boost-interprocess pbs

c++ - Memoria compartida, MPI y sistemas de colas.



shared-memory boost-interprocess (8)

Mi aplicación Unix / Windows C ++ ya está en paralelo utilizando MPI: el trabajo se divide en N CPU y cada fragmento se ejecuta en paralelo, bastante eficiente, muy buena escala de velocidad, el trabajo se realiza correctamente.

Pero algunos de los datos se repiten en cada proceso, y por razones técnicas, estos datos no se pueden dividir fácilmente en MPI (...). Por ejemplo:

  • 5 Gb de datos estáticos, exactamente lo mismo cargado para cada proceso
  • 4 Gb de datos que pueden distribuirse en MPI, cuanto más CPU se utilizan, más pequeña es la RAM por CPU.

En un trabajo de 4 CPU, esto significaría al menos una carga de RAM de 20 Gb, la mayoría de la memoria "desperdiciada", esto es horrible.

Estoy pensando en usar la memoria compartida para reducir la carga general, el fragmento "estático" se cargaría solo una vez por computadora.

Entonces, la pregunta principal es:

  • ¿Hay alguna forma estándar de MPI para compartir la memoria en un nodo? ¿Algún tipo de biblioteca disponible + gratis?

    • De lo contrario, usaría boost.interprocess y usaría llamadas MPI para distribuir identificadores de memoria compartida locales.
    • La memoria compartida sería leída por un "maestro local" en cada nodo, y compartida solo para lectura. No es necesario ningún tipo de semáforo / sincronización, porque no cambiará.
  • ¿Algún golpe de rendimiento o problemas particulares a tener en cuenta?

    • (No habrá ninguna "cadena" o estructuras de datos demasiado extrañas, todo puede reducirse a matrices y punteros de estructura)
  • El trabajo se ejecutará en un sistema de colas PBS (o SGE), en el caso de un proceso de salida no limpia, me pregunto si esos limpiarán la memoria compartida específica del nodo.


Con MPI-2 tiene RMA (acceso a memoria remota) a través de funciones como MPI_Put y MPI_Get. El uso de estas funciones, si su instalación de MPI las admite, ciertamente lo ayudaría a reducir el consumo total de memoria de su programa. El costo es una complejidad agregada en la codificación, pero eso es parte de la diversión de la programación paralela. Por otra parte, te mantiene en el dominio de MPI.


MPI-3 ofrece ventanas de memoria compartida (ver, por ejemplo, MPI_Win_allocate_shared() ), que permite el uso de la memoria compartida en el nodo sin dependencias adicionales.


Me encontré con este problema en la pequeña cuando usé MPI hace unos años.

No estoy seguro de que el SGE entienda los archivos asignados a la memoria. Si está distribuyendo contra un clúster de beowulf, sospecho que va a tener problemas de coherencia. ¿Podrías discutir un poco sobre tu arquitectura multiprocesador?

Mi proyecto de enfoque sería configurar una arquitectura en la que cada parte de los datos pertenezca a una CPU definida. Habría dos subprocesos: un subproceso que es un interlocutor bidireccional MPI y un subproceso para calcular el resultado. Tenga en cuenta que MPI y los hilos no siempre juegan bien juntos.


No he trabajado con MPI, pero si es como otras bibliotecas de IPC que he visto que ocultan si otros subprocesos / procesos / lo que sea en la misma máquina o en otras diferentes, entonces no podrá garantizar la memoria compartida. Sí, podría manejar la memoria compartida entre dos nodos en la misma máquina, si esa máquina proporcionara la memoria compartida. Pero tratar de compartir la memoria entre nodos en diferentes máquinas sería muy difícil en el mejor de los casos, debido a los complejos problemas de coherencia planteados. Yo esperaría que simplemente no esté implementado.

En la práctica, si necesita compartir memoria entre nodos, lo mejor que puede hacer es hacerlo fuera de MPI. No creo que necesites usar la memoria compartida estilo boost.interprocess , ya que no estás describiendo una situación en la que los diferentes nodos están realizando cambios precisos en la memoria compartida; Es de solo lectura o particionado.

Las respuestas de John y deus cubren cómo mapear en un archivo, que es definitivamente lo que quiere hacer para los datos estáticos de 5 Gb (¿giga bit ?). Los datos por CPU suenan como lo mismo, y solo necesita enviar un mensaje a cada nodo que le diga qué parte del archivo debe capturar. El sistema operativo debe ocuparse de asignar la memoria virtual a la memoria física a los archivos.

En cuanto a la limpieza ... Supongo que no realiza ninguna limpieza de la memoria compartida, pero los archivos de mmap ed deben limpiarse ya que los archivos se cierran (lo que debería liberar sus asignaciones de memoria) cuando se limpia un proceso. No tengo idea de las advertencias que tiene CreateFileMapping etc.

La "memoria compartida" real (es decir, boost.interprocess ) no se limpia cuando un proceso muere. Si es posible, recomiendo intentar matar un proceso y ver lo que queda atrás.


No sé mucho acerca de Unix, y no sé qué es MPI. Pero en Windows, lo que está describiendo es una coincidencia exacta para un objeto de asignación de archivos.

Si esta información está incrustada en su .EXE o un .DLL que carga, entonces se compartirá automáticamente entre todos los procesos. El desmontaje de su proceso, incluso como resultado de un bloqueo, no causará fugas ni bloqueos inéditos de sus datos. Sin embargo, un .dll de 9 Gb suena un poco dudoso. Así que esto probablemente no funcione para ti.

Sin embargo, puede poner sus datos en un archivo, luego MapViewOfFile y MapViewOfFile en él. La asignación puede ser de solo lectura y puede asignar todo o parte del archivo a la memoria. Todos los procesos compartirán páginas que se asignan al mismo objeto CreateFileMapping subyacente. es una buena práctica cerrar las vistas sin mapear y los manejadores, pero si no lo hace, el sistema operativo lo hará por usted en el desmontaje.

Tenga en cuenta que, a menos que esté ejecutando x64, no podrá asignar un archivo de 5Gb a una sola vista (o incluso a un archivo de 2Gb, 1Gb podría funcionar). Pero dado que estás hablando de que esto ya está funcionando, supongo que solo eres x64.


Si almacena sus datos estáticos en un archivo, puede usar mmap en unix para obtener acceso aleatorio a los datos. Los datos se paginarán a medida que necesite acceso a un bit particular de los datos. Todo lo que deberá hacer es superponer cualquier estructura binaria sobre los datos del archivo. Este es el equivalente en Unix de CreateFileMapping y MapViewOfFile mencionados anteriormente.

Por cierto, glibc usa mmap cuando se llama a malloc para solicitar más de una página de datos.


Tuve algunos proyectos con MPI en SHUT.

Como sé, hay muchas maneras de distribuir un problema usando MPI, tal vez pueda encontrar otra solución que no requiera compartir memoria, mi proyecto resolvía una ecuación de 7,000,000 y una variable de 7,000,000

Si pudiera explicar su problema, trataría de ayudarle.


Un enfoque cada vez más común en High Performance Computing (HPC) es el de los programas híbridos MPI / OpenMP. Es decir, tiene procesos N MPI y cada proceso MPI tiene M hilos. Este enfoque se asigna bien a los clústeres que consisten en nodos multiprocesador de memoria compartida.

El cambio a tal esquema de paralelización jerárquico obviamente requiere algunos cambios más o menos invasivos. OTOH, si se realiza correctamente, puede aumentar el rendimiento y la escalabilidad del código, además de reducir el consumo de memoria para los datos replicados.

Dependiendo de la implementación de MPI, es posible que no pueda realizar llamadas MPI desde todos los subprocesos. Esto se especifica mediante los argumentos required y provided a la función MPI_Init_Thread () que debe llamar en lugar de MPI_Init (). Los valores posibles son

{ MPI_THREAD_SINGLE} Only one thread will execute. { MPI_THREAD_FUNNELED} The process may be multi-threaded, but only the main thread will make MPI calls (all MPI calls are ``funneled'''' to the main thread). { MPI_THREAD_SERIALIZED} The process may be multi-threaded, and multiple threads may make MPI calls, but only one at a time: MPI calls are not made concurrently from two distinct threads (all MPI calls are ``serialized''''). { MPI_THREAD_MULTIPLE} Multiple threads may call MPI, with no restrictions.

En mi experiencia, las implementaciones modernas de MPI como Open MPI son compatibles con el MPI_THREAD_MULTIPLE más flexible. Si usa bibliotecas MPI más antiguas, o alguna arquitectura especializada, podría estar peor.

Por supuesto, no es necesario que realice subprocesos con OpenMP, esa es la opción más popular en HPC. Puede utilizar, por ejemplo, la biblioteca de subprocesos de Boost, la biblioteca de Intel TBB o los subprocesos directos o los subprocesos de Windows para el caso.