multiplicação de matrizes em cuda

30
Multiplicação de Matrizes em CUDA Divino César Soares Pontifícia Universidade Católica de Goiás (CMP/PUC-GO)

Upload: john-tortugo

Post on 26-Jun-2015

3.111 views

Category:

Education


1 download

DESCRIPTION

Exemplos de Multiplicação de Matrizes em CUDA.

TRANSCRIPT

Page 1: Multiplicação de matrizes em cuda

Multiplicação de Matrizes em CUDA

Divino César SoaresPontifícia Universidade Católica de Goiás (CMP/PUC-GO)

Page 2: Multiplicação de matrizes em cuda

O Problema

• Duas matrizes de entrada: A e B. Que são quadradas e possuem os mesmos valores para suas dimensões: LARGURA x LARGURA.

• 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:

for (k=1; k<=LARGURA; k++)C[i][j] += (A[i][k] * B[k][j]);

Page 3: Multiplicação de matrizes em cuda

Implementação Sequencialvoid multiplica(int *A[], int *B[], int *C[]) {

for (int i=1; i<=LARGURA; i++) {for (int j=1; j<=LARGURA; j++) {

for (int k=1; k<=LARGURA; k++) {C[i][j] += (A[i][k] * B[k][j]);

}}

}}

7 4 3 0

3 9 6 1

7 8 1 5

2 3 4 6

3 4 3 9

5 6 8 7

7 8 4 2

1 6 8 4

21 0 0 0

0 0 0 0

0 0 0 0

0 0 0 0

• Variáveis:L = 4

i = 1j = 1k = 1

1 2 3 4

1

2

3

4

Page 4: Multiplicação de matrizes em cuda

Implementação Sequencialvoid multiplica(int *A[], int *B[], int *C[]) {

for (int i=1; i<=LARGURA; i++) {for (int j=1; j<=LARGURA; j++) {

for (int k=1; k<=LARGURA; k++) {C[i][j] += (A[i][k] * B[k][j]);

}}

}}

7 4 3 0

3 9 6 1

7 8 1 5

2 3 4 6

3 4 3 9

5 6 8 7

7 8 4 2

1 6 8 4

33 0 0 0

0 0 0 0

0 0 0 0

0 0 0 0

• Variáveis:L = 4

i = 1j = 1k = 2

1 2 3 4

1

2

3

4

Page 5: Multiplicação de matrizes em cuda

Implementação Sequencialvoid multiplica(int *A[], int *B[], int *C[]) {

for (int i=1; i<=LARGURA; i++) {for (int j=1; j<=LARGURA; j++) {

for (int k=1; k<=LARGURA; k++) {C[i][j] += (A[i][k] * B[k][j]);

}}

}}

7 4 3 0

3 9 6 1

7 8 1 5

2 3 4 6

3 4 3 9

5 6 8 7

7 8 4 2

1 6 8 4

54 0 0 0

0 0 0 0

0 0 0 0

0 0 0 0

• Variáveis:L = 4

i = 1j = 1k = 3

1 2 3 4

1

2

3

4

Page 6: Multiplicação de matrizes em cuda

Implementação Sequencialvoid multiplica(int *A[], int *B[], int *C[]) {

for (int i=1; i<=LARGURA; i++) {for (int j=1; j<=LARGURA; j++) {

for (int k=1; k<=LARGURA; k++) {C[i][j] += (A[i][k] * B[k][j]);

}}

}}

7 4 3 0

3 9 6 1

7 8 1 5

2 3 4 6

3 4 3 9

5 6 8 7

7 8 4 2

1 6 8 4

72 0 0 0

0 0 0 0

0 0 0 0

0 0 0 0

• Variáveis:L = 4

i = 1j = 1k = 4

1 2 3 4

1

2

3

4

Page 7: Multiplicação de matrizes em cuda

Implementação Sequencialvoid multiplica(int *A[], int *B[], int *C[]) {

for (int i=1; i<=LARGURA; i++) {for (int j=1; j<=LARGURA; j++) {

for (int k=1; k<=LARGURA; k++) {C[i][j] += (A[i][k] * B[k][j]);

}}

}}

7 4 3 0

3 9 6 1

7 8 1 5

2 3 4 6

3 4 3 9

5 6 8 7

7 8 4 2

1 6 8 4

72 12 0 0

0 0 0 0

0 0 0 0

0 0 0 0

• Variáveis:L = 4

i = 1j = 2k = 1

1 2 3 4

1

2

3

4

Page 8: Multiplicação de matrizes em cuda

Implementação Sequencialvoid multiplica(int *A[], int *B[], int *C[]) {

for (int i=1; i<=LARGURA; i++) {for (int j=1; j<=LARGURA; j++) {

for (int k=1; k<=LARGURA; k++) {C[i][j] += (A[i][k] * B[k][j]);

}}

}}

7 4 3 0

3 9 6 1

7 8 1 5

2 3 4 6

3 4 3 9

5 6 8 7

7 8 4 2

1 6 8 4

72 48 0 0

0 0 0 0

0 0 0 0

0 0 0 0

• Variáveis:L = 4

i = 1j = 2k = 2

1 2 3 4

1

2

3

4

Page 9: Multiplicação de matrizes em cuda

Implementação Sequencialvoid multiplica(int *A[], int *B[], int *C[]) {

for (int i=1; i<=LARGURA; i++) {for (int j=1; j<=LARGURA; j++) {

for (int k=1; k<=LARGURA; k++) {C[i][j] += (A[i][k] * B[k][j]);

}}

}}

7 4 3 0

3 9 6 1

7 8 1 5

2 3 4 6

3 4 3 9

5 6 8 7

7 8 4 2

1 6 8 4

72 72 0 0

0 0 0 0

0 0 0 0

0 0 0 0

• Variáveis:L = 4

i = 1j = 2k = 3

1 2 3 4

1

2

3

4

Page 10: Multiplicação de matrizes em cuda

Implementação Sequencialvoid multiplica(int *A[], int *B[], int *C[]) {

for (int i=1; i<=LARGURA; i++) {for (int j=1; j<=LARGURA; j++) {

for (int k=1; k<=LARGURA; k++) {C[i][j] += (A[i][k] * B[k][j]);

}}

}}

7 4 3 0

3 9 6 1

7 8 1 5

2 3 4 6

3 4 3 9

5 6 8 7

7 8 4 2

1 6 8 4

72 99 0 0

0 0 0 0

0 0 0 0

0 0 0 0

• Variáveis:L = 4

i = 1j = 2k = 4

1 2 3 4

1

2

3

4

Page 11: Multiplicação de matrizes em cuda

Estrutura da Solução1. Alocar memória na GPU.

2. Copia dados de entrada. Da CPU para a GPU.

3. Configura execução. Número de threads e blocos.

4. Copia resultados.

cudaMalloc((void **)&A_d, size_A);cudaMalloc((void **)&B_d, size_B);cudaMalloc((void **)&C_d, size_C);

cudaMemcpy(A_d, A, size_A, cudaMemcpyHostToDevice);cudaMemcpy(B_d, B, size_B , cudaMemcpyHostToDevice);cudaMemcpy(C_d, C, size_C , cudaMemcpyHostToDevice);

dim3 gride(X, Y)dim3 bloco(Z, W, K)meu_kernel<<<gride, bloco>>>(A, B, C);

cudaMemcpy(C, C_d, size_C , cudaMemcpyDeviceToHost);

Page 12: Multiplicação de matrizes em cuda

Primeira Abordagem

Page 13: Multiplicação de matrizes em cuda

Kernel 1dim3 gride(1, 1)dim3 bloco(4, 4, 1)

dim3 gride(2, 1)dim3 bloco(4, 4, 1)

dim3 gride(1, 1)dim3 bloco(30, 30, 1)

Gride

0,0 0,1 0,2 0,3

1,0 1,1 1,2 1,3

2,0 2,1 2,2 2,3

3,0 3,1 3,2 3,3

Gride Gride

<< Launch error >>>

Bloco com 600 threadsBloco 0

Bloco 0 Bloco 1

0,0 0,1 0,2 0,3

1,0 1,1 1,2 1,3

2,0 2,1 2,2 2,3

3,0 3,1 3,2 3,3

0,0 0,1 0,2 0,3

1,0 1,1 1,2 1,3

2,0 2,1 2,2 2,3

3,0 3,1 3,2 3,3

Page 14: Multiplicação de matrizes em cuda

Kernel 1dim3 gride(1, 1)dim3 bloco(LARGURA, LARGURA, 1)

Gride

0,0 0,1 0,2 0,3

1,0 1,1 1,2 1,3

2,0 2,1 2,2 2,3

3,0 3,1 3,2 3,3

Bloco 0

LARGURA

LARGU

RA

Page 15: Multiplicação de matrizes em cuda

Kernel 1dim3 gride(1, 1)dim3 bloco(LARGURA, LARGURA, 1)

Gride

0,0 0,1 0,2 0,3

1,0 1,1 1,2 1,3

2,0 2,1 2,2 2,3

3,0 3,1 3,2 3,3

Bloco 0

LARGURA

LARGU

RA

__global__ void mulGpu(int *A[], int *B[], int *C[]) {int i = threadIdx.x;int j = threadIdx.y;

for (int k=1; k<=LARGURA; k++) {C[i][j] += (A[i][k] * B[k][j]);

}}

Kernel 1: Multiplicação na GPU

Page 16: Multiplicação de matrizes em cuda

Kernel 1

__global__ void mulGpu(int *A[], int *B[], int *C[]) {int i = threadIdx.x;int j = threadIdx.y;

for (int k=1; k<=LARGURA; k++) {C[i][j] += (A[i][k] * B[k][j]);

}}

Kernel 1: Multiplicação na GPU

7 4 3 0

3 9 6 1

7 8 1 5

2 3 4 6

3 4 3 9

5 6 8 7

7 8 4 2

1 6 8 4

0 0 0 0

0 0 0 0

0 0 0 0

0 0 0 0

1 2 3 4

1

2

3

4

Instante de tempo t=0

Page 17: Multiplicação de matrizes em cuda

Kernel 1

__global__ void mulGpu(int *A[], int *B[], int *C[]) {int i = threadIdx.x;int j = threadIdx.y;

for (int k=1; k<=LARGURA; k++) {C[i][j] += (A[i][k] * B[k][j]);

}}

Kernel 1: Multiplicação na GPU

7 4 3 0

3 9 6 1

7 8 1 5

2 3 4 6

3 4 3 9

5 6 8 7

7 8 4 2

1 6 8 4

21 12 9 0

35 20 15 0

49 28 21 0

7 4 3 0

1 2 3 4

1

2

3

4

Instante de tempo t=1

Page 18: Multiplicação de matrizes em cuda

Kernel 1

__global__ void mulGpu(int *A[], int *B[], int *C[]) {int i = threadIdx.x;int j = threadIdx.y;

for (int k=1; k<=LARGURA; k++) {C[i][j] += (A[i][k] * B[k][j]);

}}

Kernel 1: Multiplicação na GPU

7 4 3 0

3 9 6 1

7 8 1 5

2 3 4 6

3 4 3 9

5 6 8 7

7 8 4 2

1 6 8 4

12 36 24 4

18 54 36 6

24 72 48 8

18 54 36 42

1 2 3 4

1

2

3

4

Instante de tempo t=2

Page 19: Multiplicação de matrizes em cuda

Kernel 1

__global__ void mulGpu(int *A[], int *B[], int *C[]) {int i = threadIdx.x;int j = threadIdx.y;

for (int k=1; k<=LARGURA; k++) {C[i][j] += (A[i][k] * B[k][j]);

}}

Kernel 1: Multiplicação na GPU

7 4 3 0

3 9 6 1

7 8 1 5

2 3 4 6

3 4 3 9

5 6 8 7

7 8 4 2

1 6 8 4

72 99 72 73

123 159 87 88

105 138 81 40

89 134 63 70

1 2 3 4

1

2

3

4

Instante de tempo t=L

Page 20: Multiplicação de matrizes em cuda

Vantagens/Desvantagens

• Vantagem em relação a sequencial: 1. cada elemento de C é calculado em paralelo.

• Desvantagens desta abordagem:1. Restrição do formato das matrizes. Elas devem ser quadradas.2. Restrição da quantidade de elementos em cada matriz. Menor que 512.3. Usa apenas a memória global da GPU. A memória global apresenta grande latência.4. Apenas um bloco de threads, com poucas threads. Tamanho do maior bloco 22 x 22.5. Os mesmos dados são buscados várias vezes da memória.

Resultado: Subutilização dos recursos da GPU.

Page 21: Multiplicação de matrizes em cuda

Segunda Abordagem

Page 22: Multiplicação de matrizes em cuda

Kernel 2dim3 gride(2, 2)dim3 bloco(15, 15, 1)

dim3 gride(1, 1)dim3 bloco(30, 30, 1)

GrideGride

<< Launch error >>>

Bloco com 600 threads

Bloco 0, 0 Bloco 0, 1

0,0 0,1 0,2 0,3

1,0 1,1 1,2 1,3

2,0 2,1 2,2 2,3

3,0 3,1 3,2 3,3

0,0 0,1 0,2 0,3

1,0 1,1 1,2 1,3

2,0 2,1 2,2 2,3

3,0 3,1 3,2 3,3

Bloco 1, 0 Bloco 1, 1

0,0 0,1 0,2 0,3

1,0 1,1 1,2 1,3

2,0 2,1 2,2 2,3

3,0 3,1 3,2 3,3

0,0 0,1 0,2 0,3

1,0 1,1 1,2 1,3

2,0 2,1 2,2 2,3

3,0 3,1 3,2 3,3

Page 23: Multiplicação de matrizes em cuda

Kernel 2

225 threads por bloco.Total de 900 threads.

dim3 gride(2, 2)dim3 bloco(15, 15, 1)

Gride

Bloco 0, 0 Bloco 0, 1

0,0 0,1 0,2 0,3

1,0 1,1 1,2 1,3

2,0 2,1 2,2 2,3

3,0 3,1 3,2 3,3

0,0 0,1 0,2 0,3

1,0 1,1 1,2 1,3

2,0 2,1 2,2 2,3

3,0 3,1 3,2 3,3

Bloco 1, 0 Bloco 1, 1

0,0 0,1 0,2 0,3

1,0 1,1 1,2 1,3

2,0 2,1 2,2 2,3

3,0 3,1 3,2 3,3

0,0 0,1 0,2 0,3

1,0 1,1 1,2 1,3

2,0 2,1 2,2 2,3

3,0 3,1 3,2 3,3

Page 24: Multiplicação de matrizes em cuda

Kernel 2dim3 gride(2, 2)dim3 bloco(15, 15, 1)

Gride

Bloco 0, 0 Bloco 0, 1

0,0 0,1 0,2 0,3

1,0 1,1 1,2 1,3

2,0 2,1 2,2 2,3

3,0 3,1 3,2 3,3

0,0 0,1 0,2 0,3

1,0 1,1 1,2 1,3

2,0 2,1 2,2 2,3

3,0 3,1 3,2 3,3

Bloco 1, 0 Bloco 1, 1

0,0 0,1 0,2 0,3

1,0 1,1 1,2 1,3

2,0 2,1 2,2 2,3

3,0 3,1 3,2 3,3

0,0 0,1 0,2 0,3

1,0 1,1 1,2 1,3

2,0 2,1 2,2 2,3

3,0 3,1 3,2 3,3

__global__ void mulGpu2(int *A[], int *B[], int *C[]) {int i = blockIdx.x * SUB_LARGURA + threadIdx.x;int j = blockIdx.y * SUB_LARGURA + threadIdx.y;

for (int k=1; k<=LARGURA; k++) {C[i][j] += (A[i][k] * B[k][j]);

}}

Kernel 2: Multiplicação na GPU

Page 25: Multiplicação de matrizes em cuda

Kernel 2

7 4 3 0

3 9 6 1

7 8 1 5

2 3 4 6

3 4 3 9

5 6 8 7

7 8 4 2

1 6 8 4

0 0 0 0

0 0 0 0

0 0 0 0

0 0 0 0

1 2 3 4

1

2

3

4

__global__ void mulGpu2(int *A[], int *B[], int *C[]) {int i = blockIdx.x * SUB_LARGURA + threadIdx.x;int j = blockIdx.y * SUB_LARGURA + threadIdx.y;

for (int k=1; k<=LARGURA; k++) {C[i][j] += (A[i][k] * B[k][j]);

}}

Kernel 2: Multiplicação na GPU

Page 26: Multiplicação de matrizes em cuda

Kernel 2

7 4 3 0

3 9 6 1

7 8 1 5

2 3 4 6

3 4 3 9

5 6 8 7

7 8 4 2

1 6 8 4

21 12 0 0

35 20 0 0

0 0 0 0

0 0 0 0

1 2 3 4

1

2

3

4

__global__ void mulGpu2(int *A[], int *B[], int *C[]) {int i = blockIdx.x * SUB_LARGURA + threadIdx.x;int j = blockIdx.y * SUB_LARGURA + threadIdx.y;

for (int k=1; k<=LARGURA; k++) {C[i][j] += (A[i][k] * B[k][j]);

}}

Kernel 2: Multiplicação na GPU

Page 27: Multiplicação de matrizes em cuda

Kernel 2

7 4 3 0

3 9 6 1

7 8 1 5

2 3 4 6

3 4 3 9

5 6 8 7

7 8 4 2

1 6 8 4

12 36 0 0

18 54 0 0

0 0 21 0

0 0 3 0

1 2 3 4

1

2

3

4

__global__ void mulGpu2(int *A[], int *B[], int *C[]) {int i = blockIdx.x * SUB_LARGURA + threadIdx.x;int j = blockIdx.y * SUB_LARGURA + threadIdx.y;

for (int k=1; k<=LARGURA; k++) {C[i][j] += (A[i][k] * B[k][j]);

}}

Kernel 2: Multiplicação na GPU

Page 28: Multiplicação de matrizes em cuda

Kernel 2

7 4 3 0

3 9 6 1

7 8 1 5

2 3 4 6

3 4 3 9

5 6 8 7

7 8 4 2

1 6 8 4

72 99 72 73

123 159 87 88

105 138 81 40

89 134 63 70

1 2 3 4

1

2

3

4

Instante de tempo t=L __global__ void mulGpu2(int *A[], int *B[], int *C[]) {

int i = blockIdx.x * SUB_LARGURA + threadIdx.x;int j = blockIdx.y * SUB_LARGURA + threadIdx.y;

for (int k=1; k<=LARGURA; k++) {C[i][j] += (A[i][k] * B[k][j]);

}}

Kernel 2: Multiplicação na GPU

Page 29: Multiplicação de matrizes em cuda

Vantagens/Desvantagens

• Vantagem em relação a sequencial: 1. cada elemento de C é calculado em paralelo.

• Vantagens em relação a primeira abordagem: 1. Matrizes de tamanho arbitrário.2. Quantidade maior de blocos, permite melhor utilização dos recursos da GPU.

• Desvantagens desta abordagem:1. Restrição do formato das matrizes. Elas devem ser quadradas.2. Usa apenas a memória global da GPU. A memória global apresenta grande latência.3. Os mesmos dados são buscados várias vezes da memória.

Resultado: Muito tempo gasto esperando transferência de dados.

Page 30: Multiplicação de matrizes em cuda

Dúvidas?