Técnicas para desenvolvimento e aceleração de códigos científicos


Prof. Edson Borin
Instituto de Computação
Universidade Estadual de Campinas
Raul Baldin
Faculdade de Engenharia Civil, Arquitetura e Urbanismo
Universidade Estadual de Campinas

Atividade Prática: Vetorização de código

Nesta atividade, verificaremos como a vetorização de código pode melhorar o desempenho de aplicações científicas.

Conceitos Básicos

Processadores modernos possuem instruções e unidades funcionais vetoriais que são capazes de carregar e realizar operações com múltiplos dados consecutivos na memória (vetores) de uma só vez. Por exemplo, a instrução addpd xmm1, xmm2/m128 (Packed single-precision floating point add) é uma instrução dos processadores x86 modernos capaz de somar quatro valores de ponto flutuante simples (float) em uma única instrução. Os registradores xmm são registradores de 128 bits que são capazes de armazenar quatro valores de ponto flutuante simples (32 bits).

Nesta atividade, compararemos o desempenho de um algoritmo de produto interno de vetores ingênuo com o mesmo algoritmo vetorizado manualmente.

Atividades

Cada atividade possui um arquivo com código fonte para executar o algoritmo, medir o tempo de execução e reportar o tempo e o desempenho do acesso à memória, em Gigabytes por segundo (GB/s). O algoritmo é executado múltiplas vezes e os tempos médio, menor e maior são reportados.

Produto interno ingênuo

Ao inspecionar o código do programa, você pode observar que:

Qual foi a maior vazão da memória atingida em seu computador?

Produto interno vetorizado

Ao inspecionar o código do programa, você pode observar que:

Execute este kernel e compare o desempenho do mesmo com o desempenho do produto interno ingênuo.

Qual a relação de desempenho entre este algoritmo e o algoritmo ingênuo?

Desempenho com os dados na cache

Os programas acima executam a rotina clean_caches() para remover os dados da cache antes de executar a próxima iteração do kernel. O que acontece com o desempenho dos programas acima se deixarmos de remover os dados da cache entre iterações do kernel?

Desafio

Inspecione o código em linguagem de montagem compare com o código em C.
Para gerar o código em linguagem de montagem, execute:

gcc -O3 -DMMC_USE_SSE -msse3 kernel7-inner_prod_vec.c -S  -o kernel7-inner_prod_vec.s
Procure pelas rotinas inner_prod (algoritmo ingênuo) e inner_prod_vec. Você consegue identificar o laço principal de cada rotina?
Dica: procure pela instrução jne label (jump not equal), onde label é um rótulo definido antes desta instrução.
Compare as instruções de ambos os laços e estime o número de instruções executadas por cada laço.