Atividade 05
Leia com atenção as instruções abaixo.
Valor: 2,0 pontos na 1ª Nota.
Data da Entrega Limite: 21/05/2022
Formato de Entrega: envie um .pdf com a resolução, feito em meios digitais, para o chat privado do professor no Slack.
A atividade é individual.
Questão 01 - 1,0 Ponto
Desempenho da Convolução. Considere uma CPU com um único núcleo funcionando a 2.5 GHz e capaz de realizar 8 operações em ponto flutuante de precisão simples por ciclo. Essa CPU está conectada a um módulo DRAM com pico de transferência de memória em 25.6 GB/s. Ela tem um cache de 256 KB funcionando na mesma velocidade de um registrador. Queremos calcular a convolução de uma imagem 2D \(I\) de tamanho \(n \times n\) armazenada na memória principal com uma máscara \(M\) de tamanho \((2k+1)\times(2k+1)\), isto é, queremos calcular uma imagem \(C\) de tamanho \(n \times n\) com:
\begin{equation} C[x][y] = \sum_{i=-k}^{k}\sum_{j=-k}^{k}{I[x+i][y+j] \times M[k-i][k-j]}\text{ para todo } \{ 0 \le x,y \le n - 1 \} \end{equation}
Na equação acima, temos \(I[x+i][y+j] = 0\) se \(x + i \lt 0\) ou \(x + i \ge n\) ou \(y + j \lt 0\) ou \(y + j \ge n\).
Responda e justifique os seguintes itens.
- Estabeleça um limite superior no desempenho alcançável deste sistema para calcular a convolução de uma imagem \(I\) com valores reais de tamanho \(256 \times 256\) e uma máscara \(M\) de tamanho \(1 \times 1\).
- Faça o mesmo para uma máscara \(5 \times 5\).
- Qual seria uma boa estratégia para caching se \(I\) for muitas vezes maior que a cache?
Questão 02 - 1,0 Ponto
Linhas de Cache e Vetorização. Considere uma CPU com uma linha de cache de tamanho \(L = sizeof(float) \times 16\) e duas matrizes quadradas \(A, B \in float^{N \times N}\), cada uma com tamanho \(N = 1024\). Nos items a seguir, queremos calcular \(C = A + B\) processando as entradas \(C_{ij} = A_{ij} + B_{ij}\) para todo \(i,j \in {0, ..., N-1}\).
Calcule o número total de erros de cache na função row_wise_add:
// row-major-order addition void row_wise_add(float *A, float *B, float *C, size_t N) { for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) C[i*N + j] = A[i*N + j] + B[i*N + j]; }Faça o mesmo para a função column_wise_add:. Qual das duas funções tem melhor desempenho?
// column-major-order addition void column_wise_add(float *A, float *B, float *C, size_t N) { for (int j = 0; j < N; j++) for (int i = 0; i < N; i++) C[i*N + j] = A[i*N + j] + B[i*N + j]; }Usando a função intríseca __mm256_load_ps você pode carregar 8 valores de precisão simples em ponto flutuante de uma vez de um vetor alinhado e armazená-los em uma variável local __mm256 tmp. A função equivalente __mm256_store_ps pode ser usada para armazenar o vetor de volta na memória. Encontre o comando apropriado para somar duas variáveis do tipo __mm256. Depois implemente uma versão AVX da função row_wise_add:.
Compare o tempo de execução das três versões acima.