outubro 27, 2013

Dica: CUDA no Matlab (and it's free!!!)

Depois da dica para o uso de OpenCL no Matlab, vai aqui uma dica para quem prefere usar a linguagem da Nvidia para programação em placas de vídeo. Os mais espertos e avançados vão se antecipar, dizendo que as versões mais recentes do "Parallel Computing Toolbox" do Matlab já fazem a ponte entre a interface gráfica do Matlab e a computação no GPU. O objetivo deste post é descrever uma solução disponível para quem não tem o toolbox, ou prefere colocar a mão na massa de forma mais explícita, escrevendo MEX-files para otimizar procedimentos mesmo fora do GPU.

Para usar os recursos em CUDA, é necessário estabelecer uma ponte entre o Matlab e a linguagem básica de programação (C/C++, neste caso) e uma segunda ponte, entre a linguagem de programação e o código em CUDA. O primeiro passo é trivial, com o uso de MEX-files escritos para otimizar funções no Matlab (um bom tutorial aqui). Para o segundo passo, a Nvidia parece ter sumido com um pacote simples que fazia exatamente esta ligação.

Felizmente, ainda existem na internet boas almas que compilam pacotes ainda baseados naqueles pacotes originais da Nvidia. Eu descobri neste link um bom pacote com um excelente tutorial sobre como instalar e rodar um primeiro programa em CUDA dentro do Matlab. O tutorial é muito detalhado em termos do que precisa ser feito, funcionou sem problema algum no meu sistema. Ele vai ainda mais longe, ao ensinar como rodar o seu programa em CUDA no Matlab para avaliação no Visual Profiler da Nvidia, e como configurar uma segunda placa de vídeo exclusiva para fins computacionais no Windows 7.

Um detalhe, que me tomou um pouco de tempo para entender, é que os códigos montados pelo pacote não fazem a ponte entre o Matlab e o código em C. Ou seja, a parte do MEX-file dentro do código em CUDA deve ser escrita pelo usuário. Alguns exemplos estão disponíveis na internet, é fácil encontrar. Essencialmente, o arquivo com o kernel (função em CUDA) deve ser adicionado em um arquivo básico MEX, com o kernel chamado dentro do MEX. O MEX deve descrever os inputs, outputs e demais parâmetros da função em CUDA.

Outro detalhe importante, este fundamental para a otimização dos códigos em CUDA: ao contrário do pacote para OpenCL (grande mérito para os criadores da versão OpenCL!!!), não existe uma função específica que controle a transferência de informação entre o CPU e o GPU. Este controle é fundamental, por exemplo, caso seja necessário executar o mesmo kernel diversas vezes em um loop, por exemplo. A ausência do controle em CUDA do fluxo de informação força, ao longo da execução do loop, que todo o conjunto de informação seja passado entre o GPU e o CPU a cada passo do loop, consumindo tempo precioso de execução.

Para contornar este problema, este tutorial (seção 8) ensina como manter as variáveis dentro da GPU em execuções consecutivas do kernel em um loop, além de outras dicas interessantes sobre a integração Matlab-CUDA. Se eu entendi direito (nunca trabalhei com o "Parallel Computing Toolbox" em CUDA), parece que algum truque também é necessário para manter as informações na GPU no pacote oficial do Matlab.

Mais uma vez #ficaadica