Streams, Memoria Unificada, etc. · 2016. 4. 13. · Streams – Hardware de Fermi 20! Los streams...

36
1 Streams, Memoria Unificada, etc. Clase 15 (thanks: Carlos Bederián [email protected] IFEG-CONICET, FaMAF-UNC)

Transcript of Streams, Memoria Unificada, etc. · 2016. 4. 13. · Streams – Hardware de Fermi 20! Los streams...

Page 1: Streams, Memoria Unificada, etc. · 2016. 4. 13. · Streams – Hardware de Fermi 20! Los streams son una abstracción del hardware subyacente ! Los streams se multiplexan a 3 colas

1

Streams, Memoria Unificada, etc.

Clase 15

(thanks: Carlos Bederián [email protected]

IFEG-CONICET, FaMAF-UNC)

Page 2: Streams, Memoria Unificada, etc. · 2016. 4. 13. · Streams – Hardware de Fermi 20! Los streams son una abstracción del hardware subyacente ! Los streams se multiplexan a 3 colas

Motivación

2

! La GPU queda muy “lejos” del resto del sistema

– PCI Express 3.0 16X: 15.75 GB/s, bidireccional – Necesidad de ocultar esta latencia

! La GPU tiene poca memoria

– Necesidad de subir→procesar→bajar partes de sistemas grandes ! Si el kernel es computacionalmente intensivo (ej: MM),

puede operarse sin pérdida de performance

Page 3: Streams, Memoria Unificada, etc. · 2016. 4. 13. · Streams – Hardware de Fermi 20! Los streams son una abstracción del hardware subyacente ! Los streams se multiplexan a 3 colas

Motivación (cont.)

3

! Necesidad de concurrencia entre kernels dentro de una GPU

– A veces una GPU tiene demasiados recursos de ejecución para correr un único kernel

– Queremos poder correr múltiples kernels en paralelo

Page 4: Streams, Memoria Unificada, etc. · 2016. 4. 13. · Streams – Hardware de Fermi 20! Los streams son una abstracción del hardware subyacente ! Los streams se multiplexan a 3 colas

Kernels concurrentes

4

! Secuencial

! Cuatro en paralelo

Page 5: Streams, Memoria Unificada, etc. · 2016. 4. 13. · Streams – Hardware de Fermi 20! Los streams son una abstracción del hardware subyacente ! Los streams se multiplexan a 3 colas

cudaMemcpy(d_a,a,numBytes,cudaMemcpyHostToDevice);

some_kernel<<<1,N>>>(d_a)

cudaMemcpy(a,d_a,numBytes,cudaMemcpyDeviceToHost);

CPU - GPU Blocking

CPU - NON Blocking

Hasta ahora…

5

Page 6: Streams, Memoria Unificada, etc. · 2016. 4. 13. · Streams – Hardware de Fermi 20! Los streams son una abstracción del hardware subyacente ! Los streams se multiplexan a 3 colas

cudaMemcpy(d_a,a,numBytes,cudaMemcpyHostToDevice);some_kernel<<<1,N>>>(d_a)

some_cpu_work(a)cudaMemcpy(a,d_a,numBytes,cudaMemcpyDeviceToHost);

Overlaping CPU - GPU

6

Page 7: Streams, Memoria Unificada, etc. · 2016. 4. 13. · Streams – Hardware de Fermi 20! Los streams son una abstracción del hardware subyacente ! Los streams se multiplexan a 3 colas

Ocultamiento de latencia

7

Copia y cómputo (GeForce)

Secuencial

Doble copia y cómputo (>Tesla)

Page 8: Streams, Memoria Unificada, etc. · 2016. 4. 13. · Streams – Hardware de Fermi 20! Los streams son una abstracción del hardware subyacente ! Los streams se multiplexan a 3 colas

Streams

8

! Modelo de concurrencia dentro de la GPU

! Colas de tareas que se ejecutan secuencialmente en el orden que se despachan

! Todos los streams se ejecutan concurrentemente (si pueden)

Page 9: Streams, Memoria Unificada, etc. · 2016. 4. 13. · Streams – Hardware de Fermi 20! Los streams son una abstracción del hardware subyacente ! Los streams se multiplexan a 3 colas

Streams – Creación/Destrucción

9

cudaError_tcudaStreamCreate(cudaStream_t*s)

– Crea un nuevo stream y lo devuelve en *s

– Devuelve un cudaError_t como todo CUDA

! ¡Verificar el resultado! (nunca está de más recordarlo)

cudaStreamDestroy(cudaStream_tstream)

– Espera que stream termine su trabajo y lo destruye.

Page 10: Streams, Memoria Unificada, etc. · 2016. 4. 13. · Streams – Hardware de Fermi 20! Los streams son una abstracción del hardware subyacente ! Los streams se multiplexan a 3 colas

Streams – Ejecución

10

Encolar un kernel en un stream: kernel<<<grid,block,shared,stream>>>(...)

¡Parámetros de configuración nuevos!

shared: Memoria compartida definida en tiempo de ejecución

! Declaración en el kernel: extern__shared__Tbuf[];

! Por defecto: 0 bytes

stream: Stream donde encolar el kernel. ! Por defecto: Stream 0 (“null stream”)

– Creado automáticamente – Semántica distinta a la del resto de los streams

Page 11: Streams, Memoria Unificada, etc. · 2016. 4. 13. · Streams – Hardware de Fermi 20! Los streams son una abstracción del hardware subyacente ! Los streams se multiplexan a 3 colas

Streams – Memoria

11

! Encolar un memset: cudaMemset*Async(...,cudaStream_tstream)

! Encolar una transferencia: cudaMemcpy*Async(...,cudaStream_tstream)

OJO: La memoria del host debe ser pinned para que funcione

Page 12: Streams, Memoria Unificada, etc. · 2016. 4. 13. · Streams – Hardware de Fermi 20! Los streams son una abstracción del hardware subyacente ! Los streams se multiplexan a 3 colas

Pinned memory

12

Las copias asíncronas son manejadas por un DMA engine en la GPU ¡Pero el sistema operativo puede mudar las páginas de memoria!

CUDA provee funciones para usar memoria no paginable:

cudaMallocHost(void**ptr,size_tsize)

cudaFreeHost(void*ptr)

- Uso similar a cudaMalloc/cudaFree pero para memoria del host

- Copias más rápidas

¡Usar con precaución!

Page 13: Streams, Memoria Unificada, etc. · 2016. 4. 13. · Streams – Hardware de Fermi 20! Los streams son una abstracción del hardware subyacente ! Los streams se multiplexan a 3 colas

Streams – Sincronización

13

Esperar que termine un stream (como cudaDeviceSynchronize):

cudaStreamSynchronize(cudaStream_ts)

Consultar si un stream terminó (sin bloquear):

cudaError_tcudaStreamQuery(cudaStream_ts)

Page 14: Streams, Memoria Unificada, etc. · 2016. 4. 13. · Streams – Hardware de Fermi 20! Los streams son una abstracción del hardware subyacente ! Los streams se multiplexan a 3 colas

Streams – Eventos

14

! Esperar que termine un stream o todo el trabajo encolado en la GPU no es suficientemente fino

! Los eventos se introducen para cubrir esta necesidad – Marcadores que se insertan entre operaciones de un stream – Funciones de sincronización de eventos

Page 15: Streams, Memoria Unificada, etc. · 2016. 4. 13. · Streams – Hardware de Fermi 20! Los streams son una abstracción del hardware subyacente ! Los streams se multiplexan a 3 colas

Streams – Eventos (cont.)

15

Creación

cudaEvent_tevent;cudaEventCreate(&event);

Destrucción

cudaEventDestroy(event);

Inserción en un stream

cudaEventRecord(event,stream);

Page 16: Streams, Memoria Unificada, etc. · 2016. 4. 13. · Streams – Hardware de Fermi 20! Los streams son una abstracción del hardware subyacente ! Los streams se multiplexan a 3 colas

Streams – Eventos (cont.)

16

Ver si ocurrió un evento

cudaError_tstatus=cudaEventQuery(event);

Esperar que ocurra un evento

cudaEventSynchronize(event);

Hacer que un stream espere que se dé un evento antes de seguir:

cudaStreamWaitEvent(stream,event,0);

– Esto ocurre sin intervención del host

Page 17: Streams, Memoria Unificada, etc. · 2016. 4. 13. · Streams – Hardware de Fermi 20! Los streams son una abstracción del hardware subyacente ! Los streams se multiplexan a 3 colas

Streams – Cosas a evitar

17

Stream nulo

Sincroniza el device después de cada operación

Sincroniza el host después de cada operación, salvo algunas excepciones

Sincronización implícita cudaMallocHost/cudaHostAlloccudaMalloccudaMemcpy*/cudaMemset*(noAsync)

...

OJO: Estamos acostumbrados a esta falta de concurrencia

Page 18: Streams, Memoria Unificada, etc. · 2016. 4. 13. · Streams – Hardware de Fermi 20! Los streams son una abstracción del hardware subyacente ! Los streams se multiplexan a 3 colas

Streams – Ejemplo

18

cudaStream_tstream[3];

for(inti=0;i<3;++i)

cudaStreamCreate(&stream[i]);

for(inti=0;i<3;++i){

kernel_A<<<grid,block,0,stream[i]>>>(...);

kernel_B<<<grid,block,0,stream[i]>>>(...);

kernel_C<<<grid,block,0,stream[i]>>>(...);

}

cudaDeviceSynchronize();

for(inti=0;i<3;++i)

cudaStreamDestroy(stream[i]);

Page 19: Streams, Memoria Unificada, etc. · 2016. 4. 13. · Streams – Hardware de Fermi 20! Los streams son una abstracción del hardware subyacente ! Los streams se multiplexan a 3 colas

Streams – Ejemplo en Fermi

19

Page 20: Streams, Memoria Unificada, etc. · 2016. 4. 13. · Streams – Hardware de Fermi 20! Los streams son una abstracción del hardware subyacente ! Los streams se multiplexan a 3 colas

Streams – Hardware de Fermi

20

! Los streams son una abstracción del hardware subyacente

! Los streams se multiplexan a 3 colas en el hardware:

– Compute engine

– Device → Host engine

– Host → Device engine

! Las operaciones se ejecutan:

– En el orden que fueron despachadas

– Concurrentemente si pertenecen a distintos streams

KA1 < KA2 < KA3 = KB1 < KB2 < KB3 = KC1 < KC2 < KC3

! Fermi soporta hasta 16 grids activos concurrentes

Page 21: Streams, Memoria Unificada, etc. · 2016. 4. 13. · Streams – Hardware de Fermi 20! Los streams son una abstracción del hardware subyacente ! Los streams se multiplexan a 3 colas

Streams – Ejemplo (de nuevo)

21

cudaStream_tstream[3];

for(inti=0;i<3;++i)

cudaStreamCreate(&stream[i]);for(inti=0;i<3;++i)

kernel_A<<<grid,block,0,stream[i]>>>(...);

for(inti=0;i<3;++i)

kernel_B<<<grid,block,0,stream[i]>>>(...);

for(inti=0;i<3;++i)

kernel_C<<<grid,block,0,stream[i]>>>(...);

cudaDeviceSynchronize();

for(inti=0;i<3;++i)

cudaStreamDestroy(stream[i]);

Page 22: Streams, Memoria Unificada, etc. · 2016. 4. 13. · Streams – Hardware de Fermi 20! Los streams son una abstracción del hardware subyacente ! Los streams se multiplexan a 3 colas

Streams – Ejemplo (de nuevo)

22

Page 23: Streams, Memoria Unificada, etc. · 2016. 4. 13. · Streams – Hardware de Fermi 20! Los streams son una abstracción del hardware subyacente ! Los streams se multiplexan a 3 colas

Streams – Estrategias

23

No hay una solución buena para todos los problemas

Ver qué pasa en el profiler

Page 24: Streams, Memoria Unificada, etc. · 2016. 4. 13. · Streams – Hardware de Fermi 20! Los streams son una abstracción del hardware subyacente ! Los streams se multiplexan a 3 colas

Streams – Kepler

24

! SM 3.5 (GK110 / GK207)

– Una cola en hardware por stream

– Hasta 32 grids activos concurrentemente

– No hay dependencias ocultas entre streams

Page 25: Streams, Memoria Unificada, etc. · 2016. 4. 13. · Streams – Hardware de Fermi 20! Los streams son una abstracción del hardware subyacente ! Los streams se multiplexan a 3 colas

Fermi vs. Kepler

25

  

Hyper‐Q offers significant benefits for use in MPI‐based parallel computer systems. Legacy MPI‐based algorithms were often created to run on multi‐core CPU systems, with the amount of work assigned to each MPI process scaled accordingly. This can lead to a single MPI process having insufficient work to fully occupy the GPU. While it has always been possible for multiple MPI processes to share a GPU, these processes could become bottlenecked by false dependencies. Hyper‐Q removes those false dependencies, dramatically increasing the efficiency of GPU sharing across MPI processes.  

 

 

Hyper‐Q working with CUDA Streams: In the Fermi model shown on the left, only (C,P) & (R,X) can run concurrently due to intra‐stream dependencies caused by the single hardware work queue. The Kepler Hyper‐Q model allows all streams to run concurrently using separate work queues.  

 

 

 

 

 

Page 26: Streams, Memoria Unificada, etc. · 2016. 4. 13. · Streams – Hardware de Fermi 20! Los streams son una abstracción del hardware subyacente ! Los streams se multiplexan a 3 colas

Streams – Bibliotecas

26

Encolan sus kernels en el stream que se les configure

CUFFT cufftResultcufftSetStream(cufftHandleplan,cudaStream_tstream);

CUBLAS cublasStatus_tcublasSetStream(cublasHandle_thandle,cudaStream_tstream);

CUSPARSE cusparseStatus_tcusparseSetStream(cusparseHandle_th,cudaStream_tstream);

Page 27: Streams, Memoria Unificada, etc. · 2016. 4. 13. · Streams – Hardware de Fermi 20! Los streams son una abstracción del hardware subyacente ! Los streams se multiplexan a 3 colas

Unified Virtual Memory

27

Page 28: Streams, Memoria Unificada, etc. · 2016. 4. 13. · Streams – Hardware de Fermi 20! Los streams son una abstracción del hardware subyacente ! Los streams se multiplexan a 3 colas

Unified Virtual Memory

28

//allocomemoria

a=(float*)malloc(numBytes);

cudaMalloc(&d_a,numBytes);

//copiaH2D

cudaMemcpy(d_a,a,numBytes,cudaMemcpyHostToDevice);

//llamadoakernel

some_kernel<<<1,N>>>(d_a)

//copiaD2H

cudaMemcpy(a,d_a,numBytes,cudaMemcpyDeviceToHost);

//sigueelcódigo…

//allocomemoria

cudaMallocManaged(&a,numBytes);

//llamadoakernel

some_kernel<<<1,N>>>(a);

cudaDeviceSynchronize();

//sigueelcódigo…

Page 29: Streams, Memoria Unificada, etc. · 2016. 4. 13. · Streams – Hardware de Fermi 20! Los streams son una abstracción del hardware subyacente ! Los streams se multiplexan a 3 colas

Unified Virtual Memory

29

//variablesglobales'managed'

__device____managed__a[10];

__device____managed__x;

intmain(){

a[2]=3;

x=a[4];

//llamadoakernel

some_kernel<<<1,N>>>()

//sigueelcódigo…

}

Page 30: Streams, Memoria Unificada, etc. · 2016. 4. 13. · Streams – Hardware de Fermi 20! Los streams son una abstracción del hardware subyacente ! Los streams se multiplexan a 3 colas

Unified Virtual Memory

30

! GPU tiene acceso exclusivo durante la ejecución de un kernel.

! CPU y GPU no pueden acceder a memoria managed concurrentemente, ni siquiera si son variables distintas.

! Apéndice J de la CUDA C Programming Guide para más detalles.

Page 31: Streams, Memoria Unificada, etc. · 2016. 4. 13. · Streams – Hardware de Fermi 20! Los streams son una abstracción del hardware subyacente ! Los streams se multiplexan a 3 colas

Unified Virtual Memory: Streams

31

//variablesglobales'managed'

__device____managed__x;

__device____managed__intx,y=2;

__global__voidkernel(){

x=10;}

intmain(){

cudaStream_tstream1;

cudaStreamCreate(&stream1);

cudaStreamAttachMemAsync(stream1,&y,0,cudaMemAttachHost);

cudaDeviceSynchronize();//WaitforHostattachmenttooccur.

kernel<<<1,1,0,stream1>>>();//Note:Launchesintostream1.

y=20;//Success–akernelisrunningbut“y”

//hasbeenassociatedwithnostream.

return0;

}

Page 32: Streams, Memoria Unificada, etc. · 2016. 4. 13. · Streams – Hardware de Fermi 20! Los streams son una abstracción del hardware subyacente ! Los streams se multiplexan a 3 colas

Unified Virtual Memory: Deep copies

32

voidlaunch(dataElem*elem){

dataElem*d_elem;

char*d_name;

intnamelen=strlen(elem->name)+1;

//Allocatestorageforstructandname

cudaMalloc(&d_elem,sizeof(dataElem));

cudaMalloc(&d_name,namelen);

//Copyupeachpieceseparately,includingnew“name”pointervalue

cudaMemcpy(d_elem,elem,sizeof(dataElem),cudaMemcpyHostToDevice);

cudaMemcpy(d_name,elem->name,namelen,cudaMemcpyHostToDevice);

cudaMemcpy(&(d_elem->name),&d_name,sizeof(char*),cudaMemcpyHostToDevice);

//Finallywecanlaunchourkernel,butCPU&GPUusedifferentcopiesof“elem”

Kernel<<<...>>>(d_elem);

}

structdataElem{

intprop1;

intprop2;

char*name;

}

Page 33: Streams, Memoria Unificada, etc. · 2016. 4. 13. · Streams – Hardware de Fermi 20! Los streams son una abstracción del hardware subyacente ! Los streams se multiplexan a 3 colas

Unified Virtual Memory: Deep copies

33

voidlaunch(dataElem*elem){

Kernel<<<...>>>(elem);

}

structdataElem{

intprop1;

intprop2;

char*name;

}

Page 34: Streams, Memoria Unificada, etc. · 2016. 4. 13. · Streams – Hardware de Fermi 20! Los streams son una abstracción del hardware subyacente ! Los streams se multiplexan a 3 colas

Bibliografía

34

Justin Luitjens : Cuda Streams: Best Practices and common pitfalls- NVIDIA , GTC 2014

Steve Rennich, CUDA C/C++ Streams and Concurrency, GTC 2011

L. Nyland, S. Jones, Inside Kepler, GTC 2012

Page 35: Streams, Memoria Unificada, etc. · 2016. 4. 13. · Streams – Hardware de Fermi 20! Los streams son una abstracción del hardware subyacente ! Los streams se multiplexan a 3 colas

35

¿Che, y Thrust?

Page 36: Streams, Memoria Unificada, etc. · 2016. 4. 13. · Streams – Hardware de Fermi 20! Los streams son una abstracción del hardware subyacente ! Los streams se multiplexan a 3 colas

36

Thrust soporta streams