Técnicas de Otimização de Código para Placas de ... - UFMG
Técnicas de Otimização de Código para Placas de ... - UFMG
Técnicas de Otimização de Código para Placas de ... - UFMG
Create successful ePaper yourself
Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.
1.3. Análises e Otimizações <strong>de</strong> Divergência<br />
Muitas das otimizações que vimos na Seção 1.2, tais como<br />
ladrilhamento e alocação <strong>de</strong> registradores, são técnicas clássicas<br />
<strong>de</strong> compilação [1], po<strong>de</strong>ndo ser usadas tanto em programas<br />
sequenciais quanto em programas <strong>para</strong>lelos. Existem, contudo,<br />
otimizações <strong>de</strong> código que fazem sentido apenas quando usadas<br />
sobre máquinas SIMD, como os processadores <strong>de</strong> warps<br />
em CUDA. Esta peculiarida<strong>de</strong> <strong>de</strong>ve-se a um fenômeno <strong>de</strong>nominado<br />
execução divergente, o qual <strong>de</strong>screveremos nesta seção.<br />
Warps <strong>de</strong> threads. Em uma GPU, threads são organizadas<br />
em grupos que executam em passo único, chamados warps no<br />
jargão da NVIDIA e frentes <strong>de</strong> onda no jargão da ATI. Para enten<strong>de</strong>r<br />
as regras que governam o funcionamento das threads<br />
em um mesmo warp, imaginemos que cada warp po<strong>de</strong> usar várias<br />
unida<strong>de</strong>s lógicas e aritméticas; porém, existe somente um<br />
buscador <strong>de</strong> instruções por warp. Por exemplo, a placa Ge-<br />
Force 8800 é capaz <strong>de</strong> executar 16 warps simultaneamente.<br />
Cada warp agrupa 32 threads e po<strong>de</strong> usar 8 unida<strong>de</strong>s lógicas e<br />
aritméticas. Como existe somente um buscador <strong>de</strong> instruções,<br />
cada warp po<strong>de</strong> executar 32 instâncias da mesma instrução em<br />
quatro ciclos <strong>de</strong> pipeline da GPU. Cada uma <strong>de</strong>stas instruções,<br />
embora <strong>de</strong>signando a mesma operação, não precisa usar os<br />
mesmos dados. Trazendo <strong>de</strong> volta nossa analogia do pelotão<br />
<strong>de</strong> fuzilamento, cada soldado seria uma unida<strong>de</strong> <strong>de</strong> processamento,<br />
o capitão que lhes grita as or<strong>de</strong>ns faz o papel do buscador<br />
<strong>de</strong> instruções e cada fuzil representa os dados sendo processados.<br />
Evi<strong>de</strong>ntemente este mo<strong>de</strong>lo <strong>de</strong> execução é mais eficiente<br />
quando usado sobre aplicações regulares em que todas<br />
as threads po<strong>de</strong>m executar as mesmas tarefas. Infelizmente<br />
muitas das aplicações que gostaríamos <strong>de</strong> <strong>para</strong>lelizar não são<br />
tão regulares e divergências po<strong>de</strong>m acontecer entre as threads.<br />
Dizemos que um programa é divergente se durante sua execução<br />
threads agrupadas no mesmo warp seguem caminhos<br />
diferentes logo após terem processado um <strong>de</strong>svio condicional.<br />
Divergências ocorrem, então, <strong>de</strong>vido à <strong>de</strong>svios condicionais.<br />
A condição <strong>de</strong> <strong>de</strong>svio po<strong>de</strong> ser verda<strong>de</strong>ira <strong>para</strong> algumas threads<br />
e falsa <strong>para</strong> outras. Dado que cada warp possui acesso<br />
no máximo a uma instrução a cada ciclo <strong>de</strong> execução, em vista<br />
34