---
titulo: "Práctica P3a: Taller de paso de mensajes punto a punto en MPI"
modulo: M3
ec: EC3
contenido: "3.2, 3.3"
semanas: "7"
horas: 4
tipo: "Taller en laboratorio"
asignatura: "Sistemas Paralelos"
sigla: TEL-420
docente: "Ing. Elias Cassal Baldiviezo"
institucion: "Universidad Autónoma Juan Misael Saracho — Facultad de Ciencias Integradas de Yacuiba / F.I.R.N.T."
---

# P3a · Taller de paso de mensajes punto a punto y topología en anillo

**Contenido del programa:** §20.3 · contenidos 3.2 y 3.3  
**Horas de laboratorio:** 4 · **Modalidad:** individual  

---

## 1. Objetivo

Implementar, compilar y ejecutar aplicaciones paralelas en memoria distribuida mediante el estándar MPI en C, dominando el ciclo de vida del entorno (`MPI_Init`, `MPI_Finalize`, `MPI_Comm_rank`, `MPI_Comm_size`) y la comunicación punto a punto bloqueante (`MPI_Send`, `MPI_Recv`) y no bloqueante (`MPI_Isend`, `MPI_Irecv`), evaluando el riesgo de interbloqueos (*deadlocks*) y el solapamiento con cómputo local.

---

## 2. Requisitos previos y verificación de entorno

1. Haber estudiado los apartados 3.1, 3.2 y 3.3 de la unidad canónica de M3.
2. Contar con `mpicc` y `mpirun` en el sistema. Verificación de entorno:

```bash
cat << 'EOF' > test_mpi.c
#include <mpi.h>
#include <stdio.h>
int main(int argc, char *argv[]) {
    int rank, size;
    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &size);
    printf("Proceso %d de %d activo.\n", rank, size);
    MPI_Finalize();
    return 0;
}
EOF
mpicc test_mpi.c -o test_mpi && mpirun -np 4 ./test_mpi
```

---

## 3. Ejercicios guiados

### Ejercicio 1: Paso de testigo en anillo (*Token Ring*) bloqueante
Implementar un programa donde el proceso 0 genera un valor entero (`token = 42`) y lo envía al proceso 1. El proceso 1 incrementa el valor en 1 (`token++`) y lo envía al proceso 2, continuando cíclicamente hasta que el proceso $p - 1$ envía el valor de vuelta al proceso 0.

- **Punto crítico:** Cada proceso debe recibir de `(rank - 1 + size) % size` y enviar a `(rank + 1) % size`.
- El proceso 0 debe iniciar enviando antes de recibir para evitar un deadlock cíclico.

### Ejercicio 2: Intercambio bidireccional y demostración de Deadlock
Escribir un código donde el proceso 0 y el proceso 1 intentan enviarse simultáneamente un arreglo masivo de `double` ($N = 10^6$ elementos) utilizando `MPI_Send` seguido de `MPI_Recv`.
- Observar cómo la ejecución se congela debido al agotamiento del búfer del protocolo Eager.
- Corregir el fallo utilizando `MPI_Sendrecv` y luego mediante `MPI_Isend` / `MPI_Irecv`.

### Ejercicio 3: Ocultamiento de latencia con comunicación no bloqueante
Modificar el programa de anillo para que el envío y la recepción se inicien con `MPI_Isend` e `MPI_Irecv`. Mientras el mensaje viaja por la red, ejecutar una función de cómputo sintético (ej. cálculo de $10^7$ operaciones aritméticas flotantes). Medir con `MPI_Wtime()` el tiempo total y comprobar que el tiempo global es menor a la suma del tiempo de comunicación más el tiempo de cómputo secuencial.

---

## 4. Entregables
1. Código fuente `anillo_bloqueante.c` y `anillo_solapado.c`.
2. Breve reporte técnico respondiendo: ¿Por qué `MPI_Sendrecv` evita el interbloqueo y qué diferencia existe con `MPI_Isend`?
