Escenario:
Imagine que estamos ejecutando una simulación paralela (por ejemplo, modelar el crecimiento de la población). Tenemos un parámetro global `inicial_population` que debe ser conocido por * cada * proceso en el comunicador MPI. Solo el proceso raíz (proceso con rango 0) inicialmente conoce este valor. Usaremos `mpi_bcast` para distribuir` inicial_population` a todos los procesos.
Ejemplo de código (c ++)
`` `C ++
#Include
#Include
int main (int argc, char ** argv) {
int rango, tamaño;
doble inicial_populación; // parámetro global
Mpi_init (&argc, &argv);
Mpi_comm_rank (mpi_comm_world, &rank);
Mpi_comm_size (mpi_comm_world, &size);
// Inicializar inicial_población solo en el proceso raíz
if (rank ==0) {
inicial_population =1000.0; // Valor inicial de ejemplo
std ::cout <<"Proceso 0:Población inicial =" <
inicial_population =0.0; // Otros procesos se inicializan a un valor predeterminado (no importa)
}
// transmite la población inicial del proceso 0 a todos los procesos.
Mpi_bcast (&inicial_population, 1, mpi_double, 0, mpi_comm_world);
// Ahora, todos los procesos tienen el valor correcto de inicial_población.
// realizar cálculos de simulación utilizando los datos distribuidos
// Ejemplo:
doble crecimiento_rate =0.05; // tasa de crecimiento del 5%
Double Final_PoPulation =Inicial_PoPulation * (1.0 + Growth_Rate);
std ::cout <<"proceso" <
Mpi_finalize ();
regresar 0;
}
`` `` ``
Explicación:
1. Inicialización:
- `mpi_init (&argc, &argv)`:Inicializa el entorno MPI.
- `mpi_comm_rank (mpi_comm_world, &rank)`:obtiene el rango (id) del proceso actual.
- `mpi_comm_size (mpi_comm_world, &size)`:Obtiene el número total de procesos en el comunicador.
2. Inicialización del proceso raíz:
- `if (rank ==0)`:el código dentro de este `if` bloque se ejecuta solo en el proceso 0 (el proceso raíz).
- `Initial_PoPulation =1000.0;`:El proceso raíz establece el valor de población inicial.
3. Transmisión con `mpi_bcast`:
- `mpi_bcast (&inicial_population, 1, mpi_double, 0, mpi_comm_world);`
- `&Initial_PoPulation`:un puntero a los datos que se transmitirán (la ubicación de memoria donde se almacena` inicial_pobulation`).
- `1`:el número de elementos para transmitir (en este caso, un solo doble).
- `MPI_Double`:el tipo de datos MPI de los datos que se transmiten.
- `0`:el rango del proceso raíz (el proceso que tiene el valor original y lo está enviando).
- `mpi_comm_world`:el comunicador (en este caso, el comunicador predeterminado, incluidos todos los procesos).
4. Cálculo de simulación:
- Después de los procesos `mpi_bcast`, * Todos * tienen el valor correcto de` inicial_pobulation`.
- El código de ejemplo realiza un cálculo de simulación simple (multiplicando por una tasa de crecimiento) e imprime los resultados. En una aplicación real, aquí sería donde ocurre el cálculo paralelo utilizando los datos distribuidos.
5. Finalización:
- `mpi_finalize ()`:apaga el entorno MPI.
Cómo funciona (debajo del capó):
La función `mpi_bcast` se implementa de manera eficiente por las bibliotecas MPI. El algoritmo específico utilizado puede variar según la implementación de MPI y el tamaño de los datos que se transmiten, pero las estrategias comunes incluyen:
- Envío directo: El proceso raíz envía directamente los datos a cualquier otro proceso. Esto es simple pero puede volverse ineficiente para un gran número de procesos.
- transmisión basada en árboles: El proceso raíz envía los datos a algunos otros procesos, que luego los reenvían a otros, formando una red de distribución similar a un árbol. Esto generalmente es más escalable que el envío directo.
- Broadcast de tuberías: La raíz envía a un proceso que envía a otro, y así sucesivamente. Esto es generalmente más eficiente para mensajes grandes.
para compilar y ejecutar este código:
1. Guardar: Guarde el código como un archivo `.cpp` (por ejemplo,` broadcast_example.cpp`).
2. Compilar: Utilice un compilador de AMPI (como `MPIC ++` o `MPICC`)::
`` `Bash
mpic ++ broadcast_example.cpp -o broadcast_example
`` `` ``
3. Run: Use `mpirun` o` mpiexec` para ejecutar el programa con el número deseado de procesos:
`` `Bash
mpirun -n 4 ./broadcast_example # ejecutar con 4 procesos
`` `` ``
salida (ejemplo con 4 procesos):
`` `` ``
Proceso 0:población inicial =1000
Proceso 0:población inicial =1000, población final simulada =1050
Proceso 1:población inicial =1000, población final simulada =1050
Proceso 2:población inicial =1000, población final simulada =1050
Proceso 3:población inicial =1000, población final simulada =1050
`` `` ``
Takeaways de teclas:
- `mpi_bcast` es esencial para distribuir datos de un proceso (la raíz) a todos los demás procesos en un comunicador.
- Es una operación de * bloqueo *. Todos los procesos esperarán hasta que se complete la transmisión.
- Por lo general, se usa para distribuir datos iniciales, parámetros de configuración u otra información que necesitan todos los procesos para iniciar o continuar un cálculo paralelo.
- El proceso raíz * debe * tener el valor de datos correcto antes de la transmisión.
- Todos los procesos * deben * llamar a `mpi_bcast` (incluso el proceso raíz). Todos proporcionan una ubicación de memoria para * recibir * los datos.
Este ejemplo proporciona una comprensión fundamental de `mpi_bcast`. Puede adaptarlo a aplicaciones paralelas más complejas donde se requiere distribuir datos a todos los procesos. Recuerde elegir el proceso raíz cuidadosamente y asegurarse de que los datos a transmitir se inicialicen correctamente en ese proceso.