Paralelismo a nivel de instrucciones.
A cargo del µP.
Se lo puede ayudar.
Paralelismo de datos.
A cargo del compilador o el programador.
50 % ayuda, 50 % a mano.
Paralelismo de hilos.
A cargo del programador (casi siempre).
10 % ayuda, 90 % a mano.
Granularidad: relación entre computación y comunicación.
GPU junta TLP con DLP en una sola cosa y permite granularidad fina o media sobre un dominio restringido del paralelismo.
En realidad depende de la distancia.
Cuanto overhead de comunicación soy capaz de aguantar.
Se puede hacer paralelismo de grano fino en TLP,
pero la distancia a la memoria hace que sea IMPRACTICABLE.
Se comunican por registros, aka 1 clock.
Se comunican por DRAM, aka 100 clocks.
Esto es terrible y la implicancia es profunda.
FPU + acceso a registro = 75pJ, FPU + acceso a memoria = 1nJ
13x de diferencia.
El futuro es memoria controladada por software en cada uno de los niveles de la pirámide
Intel KNL, NVIDIA Pascal, A64FX, etc.
Uniform memory access (UMA).
Non-uniform memory access (NUMA) (todos son ccNUMA en realidad.)
Frequently Asked Questions: NUMA, SMP and AMDs Direct Connect Architecture
Datos cerca de la CPU, reducen el tráfico por los buses.
Pero ...
Las máquinas actuales con más de una pastilla son ccNUMA,
caché coherent NUMA.
¡Modelo de memoria es una problemática muy compleja!
1 P1: write(X,d)
2 ...
3 P1: read(X) = d
Eventualmente se lee el valor nuevo. No se puede leer siempre un valor viejo.
1 P1: write(X,d)
2 ...
3 ... (suficientemente separados) ...
4 ...
5 P2: read(X) = d
1 P1: write(X,d)
2 ...
3 P2: write(X,e)
4 ...
5 P3: read(X) = e
Acá no hay un "eventualmente".
Necesito un protocolo (algoritmo distribuído) de coherencia entre caches y memoria que permita:
Migración: poner el dato lo más cerca de la memoria.
Replicación: copiar datos para que la lectura simultánea de datos compartidos esté cerca de todos.
Todos los protocolos trabajan con una línea de cache de granularidad.
👆 utterly important!
Modified: la línea está solo acá y difiere de la memoria. El write-back la pasa a E.
Exclusive: la línea limpia solo está acá. Cambia a S cuando otro lee. Cambia a M si el µP la toca.
Shared: la línea está limpia, pero hay copias. Puede cambiar a I.
Empty/Invalid: la línea está sin usar.
Escribir una línea S es costoso, difundir un "¡Esta línea es inválida!".
Esto se llama RFO (request for ownership).
Tener una línea M es complejo. Snoop (interceptar) los reads, y transmitirles el dato.
Supongamos que estamos en un ccNUMA con 2 nodos de 14 núcleos cada uno (ej, ZX81 y JupiterAce).
En cada una de las caché locales está cacheada la dirección de memoria 0xFAFAFA
y marcada como Shared.
Una simple escritura de byte a la posición de memoria 0xFAFAFA
en un núcleo del nodo 1 NUMA.
1 movb $1, 16448250
Dispara
Abstracción muy simple de utilizar, con altísimos costos ocultos.
La única forma de sacarle el jugo al BW de cada pastilla E5-2680v4:
Notar que soporta ECC: error correcting code. Mucho muy importante!
Para ver que memorias DDR4 tiene 1600, 1866, 2133 o 2400, sin abrir la máquina:
1 zx81:~# dmidecode -t memory | grep "Configured Memory"
2 Configured Memory Speed: 2133 MT/s
3 Configured Memory Speed: 2133 MT/s
4 Configured Memory Speed: 2133 MT/s
5 Configured Memory Speed: 2133 MT/s
6 Configured Memory Speed: 2133 MT/s
7 Configured Memory Speed: 2133 MT/s
8 Configured Memory Speed: 2133 MT/s
9 Configured Memory Speed: 2133 MT/s
A system on Earth, at sea level, with 4 GB of RAM has a 96% percent chance of having a bit error in three days without ECC RAM. With ECC RAM, that goes down to 1.67e-10 or about one chance in six billions.
Berke Durak, On the need to use error-correcting memory, 2010.
Try to live at or below sea level, or work under a mountain à la NORAD You might also try to live in the lower floors of high-rise buildings, but avoid being near windows.
Berke Durak, Updates on the need to use error-correcting memory, 2010.
Usando bashplotlib
y STREAM.
1 $ pip install bashplotlib
2 $ wget https://www.cs.virginia.edu/stream/FTP/Code/stream.c
3 $ gcc -mcmodel=large -O3 stream.c -o stream_c.exe -fopenmp -DSTREAM_ARRAY_SIZE=500000000
4 $ for i in {1..28}; do echo -n $i","; OMP_NUM_THREADS=$i OMP_PROC_BIND=true OMP_PLACES=cores ./stream_c.exe | grep Triad | cut -d" " -f11 ; done | ~/.local/bin/scatter -c aqua
5 ------------------------------------------
6 | x|
7 | x |
8 | xx |
9 | x |
10 | x |
11 | x |
12 | x |
13 | x |
14 | |
15 | xx |
16 | x xxx |
17 | xxxx |
18 | x |
19 | x |
20 | |
21 | x |
22 | |
23 | x |
24 | |
25 | x |
26 ------------------------------------------
Según la cuentita:
BW = channels × 8 (64 bits) × F
bw(DDR4-2133) = 4×8×2133 = 68.256 GBps
por pastilla!
OMP_PROC_BIND=true OMP_PLACES=cores
para ir ocupando todos los cores primero de una pastilla y luego de la otra.Table of Contents | t |
---|---|
Exposé | ESC |
Full screen slides | e |
Presenter View | p |
Source Files | s |
Slide Numbers | n |
Toggle screen blanking | b |
Show/hide slide context | c |
Notes | 2 |
Help | h |