---
titulo: "Práctica P2c: Laboratorio de perfilado y análisis de rendimiento"
modulo: M2
ec: EC2
contenido: "2.7"
semanas: "6"
horas: 4
tipo: "Laboratorio de perfilado"
asignatura: "Sistemas Paralelos"
sigla: TEL-420
docente: "Ing. Elias Cassal Baldiviezo"
institucion: "Universidad Autónoma Juan Misael Saracho — Facultad de Ingeniería en Recursos Naturales y Tecnología"
---

# P2c · Laboratorio de perfilado y análisis de rendimiento

**Contenido del programa:** §20.2 · contenido 2.7
**Horas de laboratorio:** 4 · **Modalidad:** individual

---

## 1. Objetivo

Determinar, con datos medidos, dónde se va el tiempo en un programa paralelo; aplicar la Ley de
Amdahl para interpretar el resultado; y justificar una única optimización con su efecto cuantificado.

**Al terminar de la práctica el estudiante es capaz de:** usar un perfilador, leer sus resultados,
calcular la fracción secuencial efectiva de un programa paralelo, y decidir si una optimización
compensa su coste.

---

## 2. Por qué esta práctica es distinta a las anteriores

En P2a y P2b el resultado era previsible: `dynamic` reparte mejor que `static`, `reduction` es más
rápido que `critical`. Aquí **no hay respuestas esperadas de antemano**. Puede ocurrir que la
optimización que parece obvia empeore el programa, y descubrirlo es parte del objetivo.

---

## 3. Material de laboratorio

| Recurso | Alternativa si no está disponible |
|---|---|
| `perf` | Intel VTune (gratuito) o TAU |
| Code::Blocks / VS Code con terminal integrada | Cualquier editor con terminal |
| `htop` con la opción de ver hilos | El comando `top -H` |

Verifique la disponibilidad del perfilador antes de empezar:

```bash
perf --version || echo "perf no disponible: usar VTune"
```

---

## 4. Desarrollo de la práctica

### Paso 1: Programa de trabajo

```c
/* Sistemas Paralelos - TEL420
 * Estudiante: NOMBRE COMPLETO
 * RU / CI: XXXXXXXX
 * Practica: P2c - Laboratorio de perfilado
 */
#include <stdio.h>
#include <stdlib.h>
#include <omp.h>
#include <math.h>

#define N 4000000

/* Norma: media y desviacion tipica. El calculo es trivialmente paralelizable,
 * pero el reparto secuente es enorme frente al calculo: buen caso para Amdahl. */
int main(void) {
    double *a = malloc(N * sizeof(double));
    for (int i = 0; i < N; i++) a[i] = (double)(i % 1000) / 1000.0;

    double t_relleno = omp_get_wtime();
    /* Reparto secuencial: el 90 % del trabajo real, aqui en serie */
    double suma = 0.0;
    for (int i = 0; i < N; i++) suma += a[i];
    double media = suma / N;
    double var = 0.0;
    for (int i = 0; i < N; i++) { double d = a[i] - media; var += d * d; }
    double desviacion = (var > 0) ? (double)sqrt(var / N) : 0.0;
    double t_secuencial = omp_get_wtime() - t_relleno;

    double t1 = omp_get_wtime();
    /* Calculo paralelo: lo que OpenMP puede acelerar */
    double suma2 = 0.0;
    #pragma omp parallel for reduction(+:suma2) schedule(static)
    for (int i = 0; i < N; i++) suma2 += a[i];
    double media2 = suma2 / N;
    double var2 = 0.0;
    #pragma omp parallel for reduction(+:var2) schedule(static)
    for (int i = 0; i < N; i++) { double d = a[i] - media2; var2 += d * d; }
    double desviacion2 = (var2 > 0) ? (double)sqrt(var2 / N) : 0.0;
    double t_paralelo = omp_get_wtime() - t1;

    printf("media       secuencial = %.6f   paralela = %.6f\n", media, media2);
    printf("desviacion  secuencial = %.6f   paralela = %.6f\n", desviacion, desviacion2);
    printf("tiempo reparto secuencial = %.4f s\n", t_secuencial);
    printf("tiempo calculo  paralelo = %.4f s\n", t_paralelo);
    return 0;
}
```

```bash
gcc -O2 -fopenmp -o perfilado perfilado.c -lm
./perfilado
```

### Paso 2: Medición del tiempo según el número de hilos

```bash
for h in 1 2 4 8; do
  echo "--- $h hilos ---"
  OMP_NUM_THREADS=$h ./perfilado
done
```

Complete la tabla de $S_p$ y $E_p$ para el cálculo paralelo.

### Paso 3: Sesión de perfilado

```bash
# 1. Resumen de eventos de hardware
perf stat ./perfilado

# 2. Distribucion del tiempo entre funciones
perf record -g -- ./perfilado
perf report --stdio | head -40

# 3. Fallos de cache y ramas, que es lo que suele explicar la perdida de rendimiento
perf stat -e cache-misses,cache-references,branch-misses,branches ./perfilado
```

Con Intel VTune, el equivalente es **Hotspots** para el reparto de tiempo y **Memory Access
Analysis** para el tráfico de caché.

### Paso 4: Verificación de la Ley de Amdahl

Con los datos medidos, calcule la fracción secuencial efectiva:

$$
S_{max} = \frac{1}{s + \frac{(1 - s)}{p}}
$$

Despejando $s$ a partir del speedup medido $S_p$ y el número de hilos $p$:

$$
s = \frac{1 - \frac{S_p}{p}}{\frac{p - S_p}{p} \cdot p}
$$

Simplificando, con $s_p = S_p / p$:

$$
s = \frac{1 - s_p}{p - S_p}
$$

**Compruebe que el valor obtenido explique los resultados de la Parte 2.** Si el $s$ calculado es
muy superior al que usted esperaba, el perfilador tiene la respuesta de por qué.

### Paso 5: Una única optimización

Elija **una** de estas y aplíquela:

| Opción | Qué cambia |
|---|---|
| Paralelizar también el reparto | Eliminar la fase secuencial |
| `collapse(1)` en el bucle interno | Un solo bucle, sin segundo paso |
| Fusión de los dos bucles | Recorrer los datos una sola vez |
| `schedule(guided)` | Cambiar la política de reparto |

Mida de nuevo con los mismos números de hilos y construya la tabla antes y después.

---

## 5. Evidencias requeridas

| N° | Evidencia | Contenido |
|---|---|---|
| 1 | Salida de `./perfilado` con 1, 2, 4 y 8 hilos | Terminal |
| 2 | Salida de `perf stat` | Terminal con los contadores de caché |
| 3 | Salida de `perf report`, 20 primeras líneas | Terminal |
| 4 | Tabla de $S_p$ y $E_p$ y valor de $s$ calculado | En el informe |
| 5 | Tabla comparativa antes y después de la optimización | En el informe |
| 6 | Perfilado en ejecución con `htop -d` | Captura de pantalla |

Las seis evidencias con la marca de personalización del apartado 4.2 de
`00-marco/glosario-y-convenciones.md`.

---

## 6. Estructura del informe

Formato PDF, **máximo 4 páginas**.

| Sección | Contenido |
|---|---|
| 1. Portada | Datos institucionales, nombre, RU, fecha |
| 2. Metodología | Equipo, versión del compilador y del perfilador, procedimiento de medición |
| 3. Resultados previos | Tabla de tiempos, $S_p$ y $E_p$ antes de optimizar |
| 4. Perfilado | Distribución del tiempo, tasa de fallos de caché, interpretación |
| 5. Verificación de Amdahl | Cálculo de $s$ y contraste con la medición |
| 6. Optimización | Qué se cambió, por qué, y efecto medido con la tabla antes/después |
| 7. Conclusiones | Si la optimización compensó el esfuerzo, con argumentos |

---

## 7. Criterios de evaluación

| Criterio | Descripción | Puntaje |
|---|---|---|
| Funcionamiento | Resultados numéricos idénticos entre la versión secuencial y la paralela | 15 |
| Perfilado | Se usó el perfilador y se interpretó su salida; no se resume solo el resultado | 25 |
| Análisis de Amdahl | $s$ calculado correctamente y contrastado con los datos | 20 |
| Optimización | Una sola, justificada por el perfil y con efecto cuantificado | 25 |
| Comunicación técnica | Informe ordenado, tablas legibles, conclusiones apoyadas | 15 |
| **Total** | | **100** |

Rúbrica completa: `../rubrica-pruebas-rendimiento.md`.

---

## 8. Preguntas de análisis

1. ¿Qué parte del programa es la fracción secuencial $s$ de este ejercicio, y cuál es su peso real
   dentro del tiempo total?
2. Si paralelizara el reparto secuencial, ¿qué valor alcanzaría la eficiencia? Calcule el nuevo $s$
   y compárelo.
3. ¿Qué parte del programa es *compute bound* y cuál es *memory bound*? ¿Cómo lo demuestra el perfil?
4. ¿En qué momento del ciclo de optimización se encuentra este ejercicio, y cuál es la siguiente
   medición que haría?
5. ¿Qué ocurriría si aumentara el número de hilos a 32 en una máquina de 8 núcleos físicos?

---

*Práctica derivada de `00-marco/programa-docente-TEL420-V2.docx`, apartado 20.2, contenido 2.7.*
