Skip to content

Commit 802428d

Browse files
committed
up
1 parent 5990ab3 commit 802428d

2 files changed

Lines changed: 386 additions & 1 deletion

File tree

material/aulas/aula23/index.md

Lines changed: 385 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,385 @@
1+
2+
Exercícios de aquecimento para a PF
3+
4+
### Multiplicação de Matrizes
5+
6+
Reduza os acessos à memória global, aplicando a otimização com tilling e shared memory.
7+
8+
```cpp
9+
#include <stdio.h>
10+
#include <cuda_runtime.h>
11+
12+
#define N 2048
13+
14+
__global__ void matMul(float *A, float *B, float *C) {
15+
int row = blockIdx.y * blockDim.y + threadIdx.y;
16+
int col = blockIdx.x * blockDim.x + threadIdx.x;
17+
18+
if (row < N && col < N) {
19+
20+
float sum = 0.0f;
21+
22+
for (int k = 0; k < N; k++) {
23+
sum += A[row * N + k] * B[k * N + col];
24+
}
25+
26+
C[row * N + col] = sum;
27+
}
28+
}
29+
30+
int main() {
31+
32+
size_t size = N * N * sizeof(float);
33+
34+
float *A, *B, *C;
35+
float *d_A, *d_B, *d_C;
36+
37+
A = (float*)malloc(size);
38+
B = (float*)malloc(size);
39+
C = (float*)malloc(size);
40+
41+
for (int i = 0; i < N * N; i++) {
42+
A[i] = 1.0f;
43+
B[i] = 1.0f;
44+
}
45+
46+
cudaMalloc(&d_A, size);
47+
cudaMalloc(&d_B, size);
48+
cudaMalloc(&d_C, size);
49+
50+
cudaMemcpy(d_A, A, size, cudaMemcpyHostToDevice);
51+
cudaMemcpy(d_B, B, size, cudaMemcpyHostToDevice);
52+
53+
dim3 threads(16,16);
54+
dim3 blocks((N+15)/16, (N+15)/16);
55+
56+
matMul<<<blocks, threads>>>(d_A, d_B, d_C);
57+
58+
cudaMemcpy(C, d_C, size, cudaMemcpyDeviceToHost);
59+
60+
printf("Resultado: %f\n", C[0]);
61+
62+
cudaFree(d_A);
63+
cudaFree(d_B);
64+
cudaFree(d_C);
65+
66+
free(A);
67+
free(B);
68+
free(C);
69+
70+
return 0;
71+
}
72+
```
73+
74+
75+
76+
### Estimativa de pi com Monte Carlo em CUDA
77+
78+
Aplique técnicas de otimização em GPU para reduzir em pelo menos 2x o tempo de execução deste algoritmo sem comprometer a precisão do resultado:
79+
80+
```cpp
81+
#include <stdio.h>
82+
#include <stdlib.h>
83+
#include <time.h>
84+
#include <math.h>
85+
86+
#define THREADS 256
87+
#define BLOCKS 256
88+
#define SAMPLES_PER_THREAD 70000
89+
90+
int main() {
91+
92+
/*
93+
Contador de pontos que ficaram dentro
94+
do círculo unitário.
95+
*/
96+
unsigned long long count = 0;
97+
98+
/*
99+
Calcula o total de amostras que serão geradas.
100+
*/
101+
unsigned long long total_samples =
102+
(unsigned long long)THREADS *
103+
BLOCKS *
104+
SAMPLES_PER_THREAD;
105+
106+
/*
107+
Inicializa o gerador de números aleatórios.
108+
*/
109+
srand(time(NULL));
110+
111+
// Marca o tempo inicial
112+
clock_t start = clock();
113+
114+
for (unsigned long long i = 0; i < total_samples; i++) {
115+
116+
/*
117+
Gera coordenadas aleatórias entre 0 e 1.
118+
*/
119+
float x =
120+
(float)rand() / (float)RAND_MAX;
121+
122+
float y =
123+
(float)rand() / (float)RAND_MAX;
124+
125+
/*
126+
Calcula a distância até a origem.
127+
128+
Uso de sqrt() é desnecessário,
129+
pois poderíamos comparar apenas
130+
a distância ao quadrado.
131+
132+
Isso torna o código mais lento.
133+
*/
134+
float dist =
135+
sqrt((x * x) + (y * y));
136+
137+
/*
138+
Verifica se o ponto está dentro
139+
do círculo unitário.
140+
*/
141+
if (dist <= 1.0f) {
142+
count++;
143+
}
144+
}
145+
146+
// Marca o tempo final
147+
clock_t end = clock();
148+
149+
/*
150+
Estimativa de PI usando Monte Carlo.
151+
152+
pi ≈ 4 * pontos_dentro / total
153+
*/
154+
double pi =
155+
4.0 * ((double)count / (double)total_samples);
156+
157+
// Calcula o tempo de execução
158+
double elapsed =
159+
(double)(end - start) / CLOCKS_PER_SEC;
160+
161+
// Exibe os resultados
162+
printf("Estimativa de PI : %.4f\n", pi);
163+
printf("Pontos dentro : %llu\n", count);
164+
printf("Total de pontos : %llu\n", total_samples);
165+
printf("Tempo total : %.4f segundos\n", elapsed);
166+
167+
return 0;
168+
}
169+
```
170+
171+
### Exercício: Busca de Nonce
172+
173+
174+
Otimize o código aplicando técnicas de otimização em GPU
175+
176+
```cpp
177+
// ============================================================
178+
// Simulação simples de mineração de blockchain
179+
//
180+
// O programa:
181+
// 1. Gera hashes a partir de um bloco + nonce
182+
// 2. Procura hashes com zeros iniciais
183+
// 3. Mede o tempo necessário para minerar
184+
//
185+
// Implementação sequencial em CPU.
186+
// ============================================================
187+
188+
#include <iostream> // Entrada e saída (cout)
189+
#include <string> // Manipulação de strings
190+
#include <chrono> // Medição de tempo
191+
#include <functional> // std::hash
192+
#include <sstream> // stringstream
193+
#include <iomanip> // setw, setfill
194+
195+
/*
196+
Define a dificuldade da mineração.
197+
*/
198+
#define DIFICULDADE 7
199+
200+
/*
201+
Função responsável por gerar um hash hexadecimal.
202+
203+
Recebe:
204+
uma string de entrada
205+
206+
Retorna:
207+
uma string hexadecimal simulando um hash.
208+
*/
209+
std::string gerarHash(const std::string& entrada) {
210+
211+
/*
212+
std::hash é uma função de hash da biblioteca padrão.
213+
214+
NÃO é SHA-256 real, mas serve para simular
215+
mineração de blockchain.
216+
*/
217+
std::hash<std::string> hash_fn;
218+
219+
/*
220+
Calcula o hash numérico da entrada.
221+
*/
222+
size_t valor = hash_fn(entrada);
223+
224+
/*
225+
stringstream será usado para converter
226+
o valor numérico para hexadecimal.
227+
*/
228+
std::stringstream ss;
229+
230+
/*
231+
std::hex:
232+
converte para hexadecimal
233+
234+
std::setw(16):
235+
largura mínima de 16 caracteres
236+
237+
std::setfill('0'):
238+
completa com zeros à esquerda
239+
*/
240+
ss << std::hex
241+
<< std::setw(16)
242+
<< std::setfill('0')
243+
<< valor;
244+
245+
/*
246+
Retorna o hash em formato string.
247+
*/
248+
return ss.str();
249+
}
250+
251+
/*
252+
Verifica se o hash possui
253+
determinada quantidade de zeros iniciais.
254+
*/
255+
bool hashValido(
256+
const std::string& hash,
257+
int dificuldade
258+
) {
259+
260+
/*
261+
Percorre os primeiros caracteres do hash.
262+
*/
263+
for (int i = 0; i < dificuldade; i++) {
264+
265+
/*
266+
Se algum caractere não for '0',
267+
o hash não é válido.
268+
*/
269+
if (hash[i] != '0') {
270+
return false;
271+
}
272+
}
273+
274+
return true;
275+
}
276+
277+
int main() {
278+
279+
/*
280+
Conteúdo do bloco.
281+
282+
Em uma blockchain real poderia conter:
283+
- transações
284+
- timestamp
285+
- hash anterior
286+
- etc.
287+
*/
288+
std::string bloco =
289+
"Transacao A -> B";
290+
291+
/*
292+
Nonce inicial.
293+
294+
O nonce será incrementado continuamente
295+
até encontrar um hash válido.
296+
*/
297+
int nonce = 0;
298+
299+
// Armazena o hash calculado
300+
std::string hash;
301+
302+
/*
303+
Marca o instante inicial da mineração.
304+
*/
305+
auto inicio =
306+
std::chrono::high_resolution_clock::now();
307+
308+
/*
309+
Loop principal da mineração.
310+
311+
A cada iteração:
312+
bloco + nonce -> hash
313+
*/
314+
while (true) {
315+
316+
/*
317+
Concatena o bloco com o nonce.
318+
319+
*/
320+
std::string tentativa =
321+
bloco + std::to_string(nonce);
322+
323+
/*
324+
Calcula o hash da tentativa atual.
325+
*/
326+
hash = gerarHash(tentativa);
327+
328+
/*
329+
Verifica se o hash atende
330+
à dificuldade.
331+
*/
332+
if (hashValido(hash, DIFICULDADE)) {
333+
334+
/*
335+
Marca o instante final.
336+
*/
337+
auto fim =
338+
std::chrono::high_resolution_clock::now();
339+
340+
/*
341+
Calcula o tempo total
342+
de mineração em segundos.
343+
*/
344+
double tempo =
345+
std::chrono::duration<double>(
346+
fim - inicio
347+
).count();
348+
349+
// Exibe informações do bloco minerado
350+
std::cout << "Bloco minerado!\n";
351+
352+
// Nonce encontrado
353+
std::cout
354+
<< "Nonce: "
355+
<< nonce
356+
<< "\n";
357+
358+
// Hash válido encontrado
359+
std::cout
360+
<< "Hash : "
361+
<< hash
362+
<< "\n";
363+
364+
// Tempo gasto na mineração
365+
std::cout
366+
<< "Tempo: "
367+
<< tempo
368+
<< " segundos\n";
369+
370+
/*
371+
Encerra a mineração.
372+
*/
373+
break;
374+
}
375+
376+
/*
377+
Testa o próximo nonce.
378+
*/
379+
nonce++;
380+
}
381+
382+
return 0;
383+
}
384+
```
385+

mkdocs.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ nav:
5454
- "Aula 20 - Revisão II - Estratégias de otimização em GPU" : aulas/aula20/index.md
5555
- "Aula 21 - APS2 no Cluster Santos Dumont" : aulas/aula21/index.md
5656
- "Aula 22 - Exercícios preparatórios Prova Final" : aulas/aula22/index.md
57-
# - "Aula 21 - Revisão" : aulas/aula21/index.md
57+
- "Aula 23 - Exercícios preparatórios" : aulas/aula23/index.md
5858
- Suporte:
5959
- "Slides das aulas" : teoria/slides.md
6060
- "Aula 01" : teoria/aula01/compilar-executar-C++.md

0 commit comments

Comments
 (0)