Multiplicação de Matrizes em CUDA<br />Divino César SoaresPontifícia Universidade Católica de Goiás (CMP/PUC-GO)<br />
O Problema<br /><ul><li> Duas matrizes de entrada: A e B. Que são quadradas e possuem os mesmos valores para suas dimensõe...
 Gerar uma matriz resultado C com as mesmas dimensões das matrizes A e B.
 Cada elemento (i, j) da matriz C é o produto (interno) da linha i de A pela coluna j de B.
 Para cada elemento (i, j) de C:</li></ul>for (k=1; k<=LARGURA; k++)<br />	C[i][j] += (A[i][k] * B[k][j]);<br />
Implementação Sequencial<br />void multiplica(int *A[], int *B[], int *C[]) {<br />for (int i=1; i<=LARGURA; i++) {<br />f...
Implementação Sequencial<br />void multiplica(int *A[], int *B[], int *C[]) {<br />for (int i=1; i<=LARGURA; i++) {<br />f...
Implementação Sequencial<br />void multiplica(int *A[], int *B[], int *C[]) {<br />for (int i=1; i<=LARGURA; i++) {<br />f...
Implementação Sequencial<br />void multiplica(int *A[], int *B[], int *C[]) {<br />for (int i=1; i<=LARGURA; i++) {<br />f...
Implementação Sequencial<br />void multiplica(int *A[], int *B[], int *C[]) {<br />for (int i=1; i<=LARGURA; i++) {<br />f...
Implementação Sequencial<br />void multiplica(int *A[], int *B[], int *C[]) {<br />for (int i=1; i<=LARGURA; i++) {<br />f...
Implementação Sequencial<br />void multiplica(int *A[], int *B[], int *C[]) {<br />for (int i=1; i<=LARGURA; i++) {<br />f...
Implementação Sequencial<br />void multiplica(int *A[], int *B[], int *C[]) {<br />for (int i=1; i<=LARGURA; i++) {<br />f...
Estrutura da Solução<br />Alocar memória na GPU.<br />Copia dados de entrada. Da CPU para a GPU.<br />Configura execução. ...
Primeira Abordagem<br />
Kernel 1<br />dim3 gride(1, 1)<br />dim3 bloco(4, 4, 1)<br />dim3 gride(2, 1)<br />dim3 bloco(4, 4, 1)<br />dim3 gride(1, ...
Kernel 1<br />dim3 gride(1, 1)<br />dim3 bloco(LARGURA, LARGURA, 1)<br />Gride<br />LARGURA<br />LARGURA<br />Bloco 0<br />
Kernel 1<br />dim3 gride(1, 1)<br />dim3 bloco(LARGURA, LARGURA, 1)<br />Gride<br />__global__voidmulGpu(int *A[], int *B[...
Kernel 1<br />1<br />Instante de tempo t=0<br />2<br />__global__voidmulGpu(int *A[], int *B[], int *C[]) {<br />int i = t...
Kernel 1<br />1<br />Instante de tempo t=1<br />2<br />__global__voidmulGpu(int *A[], int *B[], int *C[]) {<br />int i = t...
Kernel 1<br />1<br />Instante de tempo t=2<br />2<br />__global__voidmulGpu(int *A[], int *B[], int *C[]) {<br />int i = t...
Kernel 1<br />1<br />Instante de tempo t=L<br />2<br />__global__voidmulGpu(int *A[], int *B[], int *C[]) {<br />int i = t...
Vantagens/Desvantagens<br /><ul><li>Vantagem em relação a sequencial: </li></ul>cada elemento de C é calculado em paralelo...
Segunda Abordagem<br />
Kernel 2<br />dim3 gride(2, 2)<br />dim3 bloco(15, 15, 1)<br />dim3 gride(1, 1)<br />dim3 bloco(30, 30, 1)<br />Gride<br /...
Kernel 2<br />dim3 gride(2, 2)<br />dim3 bloco(15, 15, 1)<br />Gride<br />Bloco 0, 0<br />Bloco 0, 1<br />225 threads por ...
Kernel 2<br />dim3 gride(2, 2)<br />dim3 bloco(15, 15, 1)<br />Gride<br />__global__void mulGpu2(int *A[], int *B[], int *...
Kernel 2<br />1<br />2<br />__global__void mulGpu2(int *A[], int *B[], int *C[]) {<br />int i = blockIdx.x * SUB_LARGURA +...
Kernel 2<br />1<br />2<br />__global__void mulGpu2(int *A[], int *B[], int *C[]) {<br />int i = blockIdx.x * SUB_LARGURA +...
Kernel 2<br />1<br />2<br />__global__void mulGpu2(int *A[], int *B[], int *C[]) {<br />int i = blockIdx.x * SUB_LARGURA +...
Upcoming SlideShare
Loading in …5
×

Multiplicação de matrizes em cuda

3,841 views

Published on

Exemplos de Multiplicação de Matrizes em CUDA.

Published in: Education
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
3,841
On SlideShare
0
From Embeds
0
Number of Embeds
4
Actions
Shares
0
Downloads
95
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Multiplicação de matrizes em cuda

  1. 1. Multiplicação de Matrizes em CUDA<br />Divino César SoaresPontifícia Universidade Católica de Goiás (CMP/PUC-GO)<br />
  2. 2. O Problema<br /><ul><li> Duas matrizes de entrada: A e B. Que são quadradas e possuem os mesmos valores para suas dimensões: LARGURA x LARGURA.
  3. 3. Gerar uma matriz resultado C com as mesmas dimensões das matrizes A e B.
  4. 4. Cada elemento (i, j) da matriz C é o produto (interno) da linha i de A pela coluna j de B.
  5. 5. Para cada elemento (i, j) de C:</li></ul>for (k=1; k<=LARGURA; k++)<br /> C[i][j] += (A[i][k] * B[k][j]);<br />
  6. 6. Implementação Sequencial<br />void multiplica(int *A[], int *B[], int *C[]) {<br />for (int i=1; i<=LARGURA; i++) {<br />for (int j=1; j<=LARGURA; j++) {<br />for (int k=1; k<=LARGURA; k++) {<br />C[i][j] += (A[i][k] * B[k][j]);<br />}<br />}<br />}<br />}<br />1<br />2<br />3<br />4<br /><ul><li> Variáveis:</li></ul>L = 4<br /> i = 1<br /> j = 1<br /> k = 1<br />4<br />1<br />2<br />3<br />
  7. 7. Implementação Sequencial<br />void multiplica(int *A[], int *B[], int *C[]) {<br />for (int i=1; i<=LARGURA; i++) {<br />for (int j=1; j<=LARGURA; j++) {<br />for (int k=1; k<=LARGURA; k++) {<br />C[i][j] += (A[i][k] * B[k][j]);<br />}<br />}<br />}<br />}<br />1<br />2<br />3<br />4<br /><ul><li> Variáveis:</li></ul>L = 4<br /> i = 1<br /> j = 1<br /> k = 2<br />4<br />1<br />2<br />3<br />
  8. 8. Implementação Sequencial<br />void multiplica(int *A[], int *B[], int *C[]) {<br />for (int i=1; i<=LARGURA; i++) {<br />for (int j=1; j<=LARGURA; j++) {<br />for (int k=1; k<=LARGURA; k++) {<br />C[i][j] += (A[i][k] * B[k][j]);<br />}<br />}<br />}<br />}<br />1<br />2<br />3<br />4<br /><ul><li> Variáveis:</li></ul>L = 4<br /> i = 1<br /> j = 1<br /> k = 3<br />4<br />1<br />2<br />3<br />
  9. 9. Implementação Sequencial<br />void multiplica(int *A[], int *B[], int *C[]) {<br />for (int i=1; i<=LARGURA; i++) {<br />for (int j=1; j<=LARGURA; j++) {<br />for (int k=1; k<=LARGURA; k++) {<br />C[i][j] += (A[i][k] * B[k][j]);<br />}<br />}<br />}<br />}<br />1<br />2<br />3<br />4<br /><ul><li> Variáveis:</li></ul>L = 4<br /> i = 1<br /> j = 1<br /> k = 4<br />4<br />1<br />2<br />3<br />
  10. 10. Implementação Sequencial<br />void multiplica(int *A[], int *B[], int *C[]) {<br />for (int i=1; i<=LARGURA; i++) {<br />for (int j=1; j<=LARGURA; j++) {<br />for (int k=1; k<=LARGURA; k++) {<br />C[i][j] += (A[i][k] * B[k][j]);<br />}<br />}<br />}<br />}<br />1<br />2<br />3<br />4<br /><ul><li> Variáveis:</li></ul>L = 4<br /> i = 1<br /> j = 2<br /> k = 1<br />4<br />1<br />2<br />3<br />
  11. 11. Implementação Sequencial<br />void multiplica(int *A[], int *B[], int *C[]) {<br />for (int i=1; i<=LARGURA; i++) {<br />for (int j=1; j<=LARGURA; j++) {<br />for (int k=1; k<=LARGURA; k++) {<br />C[i][j] += (A[i][k] * B[k][j]);<br />}<br />}<br />}<br />}<br />1<br />2<br />3<br />4<br /><ul><li> Variáveis:</li></ul>L = 4<br /> i = 1<br /> j = 2<br /> k = 2<br />4<br />1<br />2<br />3<br />
  12. 12. Implementação Sequencial<br />void multiplica(int *A[], int *B[], int *C[]) {<br />for (int i=1; i<=LARGURA; i++) {<br />for (int j=1; j<=LARGURA; j++) {<br />for (int k=1; k<=LARGURA; k++) {<br />C[i][j] += (A[i][k] * B[k][j]);<br />}<br />}<br />}<br />}<br />1<br />2<br />3<br />4<br /><ul><li> Variáveis:</li></ul>L = 4<br /> i = 1<br /> j = 2<br /> k = 3<br />4<br />1<br />2<br />3<br />
  13. 13. Implementação Sequencial<br />void multiplica(int *A[], int *B[], int *C[]) {<br />for (int i=1; i<=LARGURA; i++) {<br />for (int j=1; j<=LARGURA; j++) {<br />for (int k=1; k<=LARGURA; k++) {<br />C[i][j] += (A[i][k] * B[k][j]);<br />}<br />}<br />}<br />}<br />1<br />2<br />3<br />4<br /><ul><li> Variáveis:</li></ul>L = 4<br /> i = 1<br /> j = 2<br /> k = 4<br />4<br />1<br />2<br />3<br />
  14. 14. Estrutura da Solução<br />Alocar memória na GPU.<br />Copia dados de entrada. Da CPU para a GPU.<br />Configura execução. Número de threads e blocos.<br />Copia resultados. <br />cudaMalloc((void **)&A_d, size_A);<br />cudaMalloc((void**)&B_d, size_B);<br />cudaMalloc((void**)&C_d, size_C);<br />cudaMemcpy(A_d, A, size_A, cudaMemcpyHostToDevice);<br />cudaMemcpy(B_d, B, size_B , cudaMemcpyHostToDevice);<br />cudaMemcpy(C_d, C, size_C , cudaMemcpyHostToDevice);<br />dim3 gride(X, Y)dim3 bloco(Z, W, K)meu_kernel<<<gride, bloco>>>(A, B, C);<br />cudaMemcpy(C, C_d, size_C , cudaMemcpyDeviceToHost);<br />
  15. 15. Primeira Abordagem<br />
  16. 16. Kernel 1<br />dim3 gride(1, 1)<br />dim3 bloco(4, 4, 1)<br />dim3 gride(2, 1)<br />dim3 bloco(4, 4, 1)<br />dim3 gride(1, 1)<br />dim3 bloco(30, 30, 1)<br />Gride<br />Gride<br />Gride<br /><< Launcherror >>><br />Bloco com 600 threads<br />Bloco 0<br />Bloco 0<br />Bloco 1<br />
  17. 17. Kernel 1<br />dim3 gride(1, 1)<br />dim3 bloco(LARGURA, LARGURA, 1)<br />Gride<br />LARGURA<br />LARGURA<br />Bloco 0<br />
  18. 18. Kernel 1<br />dim3 gride(1, 1)<br />dim3 bloco(LARGURA, LARGURA, 1)<br />Gride<br />__global__voidmulGpu(int *A[], int *B[], int *C[]) {<br />int i = threadIdx.x;<br />int j = threadIdx.y;<br />for (int k=1; k<=LARGURA; k++) {<br />C[i][j] += (A[i][k] * B[k][j]);<br />}<br />}<br />LARGURA<br />LARGURA<br />Bloco 0<br />Kernel 1: Multiplicação na GPU<br />
  19. 19. Kernel 1<br />1<br />Instante de tempo t=0<br />2<br />__global__voidmulGpu(int *A[], int *B[], int *C[]) {<br />int i = threadIdx.x;<br />int j = threadIdx.y;<br />for (int k=1; k<=LARGURA; k++) {<br />C[i][j] += (A[i][k] * B[k][j]);<br />}<br />}<br />3<br />4<br />Kernel 1: Multiplicação na GPU<br />4<br />1<br />2<br />3<br />
  20. 20. Kernel 1<br />1<br />Instante de tempo t=1<br />2<br />__global__voidmulGpu(int *A[], int *B[], int *C[]) {<br />int i = threadIdx.x;<br />int j = threadIdx.y;<br />for (int k=1; k<=LARGURA; k++) {<br />C[i][j] += (A[i][k] * B[k][j]);<br />}<br />}<br />3<br />4<br />Kernel 1: Multiplicação na GPU<br />4<br />1<br />2<br />3<br />
  21. 21. Kernel 1<br />1<br />Instante de tempo t=2<br />2<br />__global__voidmulGpu(int *A[], int *B[], int *C[]) {<br />int i = threadIdx.x;<br />int j = threadIdx.y;<br />for (int k=1; k<=LARGURA; k++) {<br />C[i][j] += (A[i][k] * B[k][j]);<br />}<br />}<br />3<br />4<br />Kernel 1: Multiplicação na GPU<br />4<br />1<br />2<br />3<br />
  22. 22. Kernel 1<br />1<br />Instante de tempo t=L<br />2<br />__global__voidmulGpu(int *A[], int *B[], int *C[]) {<br />int i = threadIdx.x;<br />int j = threadIdx.y;<br />for (int k=1; k<=LARGURA; k++) {<br />C[i][j] += (A[i][k] * B[k][j]);<br />}<br />}<br />3<br />4<br />Kernel 1: Multiplicação na GPU<br />4<br />1<br />2<br />3<br />
  23. 23. Vantagens/Desvantagens<br /><ul><li>Vantagem em relação a sequencial: </li></ul>cada elemento de C é calculado em paralelo. <br /><ul><li>Desvantagens desta abordagem:</li></ul>Restrição do formato das matrizes. Elas devem ser quadradas.<br /> Restrição da quantidade de elementos em cada matriz. Menor que 512.<br /> Usa apenas a memória global da GPU. A memória global apresenta grande latência.<br /> Apenas um bloco de threads, com poucas threads. Tamanho do maior bloco 22 x 22.<br /> Os mesmos dados são buscados várias vezes da memória.<br /> Resultado: Subutilização dos recursos da GPU.<br />
  24. 24. Segunda Abordagem<br />
  25. 25. Kernel 2<br />dim3 gride(2, 2)<br />dim3 bloco(15, 15, 1)<br />dim3 gride(1, 1)<br />dim3 bloco(30, 30, 1)<br />Gride<br />Gride<br /><< Launcherror >>><br />Bloco com 600 threads<br />Bloco 0, 0<br />Bloco 0, 1<br />Bloco 1, 0<br />Bloco 1, 1<br />
  26. 26. Kernel 2<br />dim3 gride(2, 2)<br />dim3 bloco(15, 15, 1)<br />Gride<br />Bloco 0, 0<br />Bloco 0, 1<br />225 threads por bloco.Total de 900 threads.<br />Bloco 1, 0<br />Bloco 1, 1<br />
  27. 27. Kernel 2<br />dim3 gride(2, 2)<br />dim3 bloco(15, 15, 1)<br />Gride<br />__global__void mulGpu2(int *A[], int *B[], int *C[]) {<br />int i = blockIdx.x * SUB_LARGURA + threadIdx.x;<br />int j = blockIdx.y * SUB_LARGURA + threadIdx.y;<br />for (int k=1; k<=LARGURA; k++) {<br />C[i][j] += (A[i][k] * B[k][j]);<br />}<br />}<br />Bloco 0, 0<br />Bloco 0, 1<br />Kernel 2: Multiplicação na GPU<br />Bloco 1, 0<br />Bloco 1, 1<br />
  28. 28. Kernel 2<br />1<br />2<br />__global__void mulGpu2(int *A[], int *B[], int *C[]) {<br />int i = blockIdx.x * SUB_LARGURA + threadIdx.x;<br />int j = blockIdx.y * SUB_LARGURA + threadIdx.y;<br />for (int k=1; k<=LARGURA; k++) {<br />C[i][j] += (A[i][k] * B[k][j]);<br />}<br />}<br />3<br />4<br />Kernel 2: Multiplicação na GPU<br />4<br />1<br />2<br />3<br />
  29. 29. Kernel 2<br />1<br />2<br />__global__void mulGpu2(int *A[], int *B[], int *C[]) {<br />int i = blockIdx.x * SUB_LARGURA + threadIdx.x;<br />int j = blockIdx.y * SUB_LARGURA + threadIdx.y;<br />for (int k=1; k<=LARGURA; k++) {<br />C[i][j] += (A[i][k] * B[k][j]);<br />}<br />}<br />3<br />4<br />Kernel 2: Multiplicação na GPU<br />4<br />1<br />2<br />3<br />
  30. 30. Kernel 2<br />1<br />2<br />__global__void mulGpu2(int *A[], int *B[], int *C[]) {<br />int i = blockIdx.x * SUB_LARGURA + threadIdx.x;<br />int j = blockIdx.y * SUB_LARGURA + threadIdx.y;<br />for (int k=1; k<=LARGURA; k++) {<br />C[i][j] += (A[i][k] * B[k][j]);<br />}<br />}<br />3<br />4<br />Kernel 2: Multiplicação na GPU<br />4<br />1<br />2<br />3<br />
  31. 31. Kernel 2<br />1<br />Instante de tempo t=L<br />2<br />__global__void mulGpu2(int *A[], int *B[], int *C[]) {<br />int i = blockIdx.x * SUB_LARGURA + threadIdx.x;<br />int j = blockIdx.y * SUB_LARGURA + threadIdx.y;<br />for (int k=1; k<=LARGURA; k++) {<br />C[i][j] += (A[i][k] * B[k][j]);<br />}<br />}<br />3<br />4<br />Kernel 2: Multiplicação na GPU<br />4<br />1<br />2<br />3<br />
  32. 32. Vantagens/Desvantagens<br /><ul><li>Vantagem em relação a sequencial: </li></ul>cada elemento de C é calculado em paralelo. <br /><ul><li>Vantagens em relação a primeira abordagem: </li></ul>Matrizes de tamanho arbitrário.<br />Quantidade maior de blocos, permite melhor utilização dos recursos da GPU.<br /><ul><li>Desvantagens desta abordagem:</li></ul>Restrição do formato das matrizes. Elas devem ser quadradas.<br />Usa apenas a memória global da GPU. A memória global apresenta grande latência.<br />Os mesmos dados são buscados várias vezes da memória.<br /> Resultado: Muito tempo gasto esperando transferência de dados.<br />
  33. 33. Dúvidas?<br />

×