
Hoje em dia é normal ouvir do vendedor “Esse computador é ótimo! Tem 4 GB de RAM e é um Core Duo!“. Apesar de, na maioria das vezes, a pessoa nem fazer idéia do que diabos é um Core Duo. Mas tudo bem, esse é o papel do vendedor, certo? É claro que qualquer entendido sabe que isso não qualifica o produto como “bom“, longe disso, temos que levar em conta muitos outros detalhes que pessoas que não são da área não entendem.
Com a chegada dos processadores de múltiplos núcleos, o marketing foi direcionao à esse fator e esqueceu de que memória cache e barramento contam MUITO no desempenho. A maioria das pessoas não entendem, por exemplo, que um processador de 2 núcleos de 2.0 GHz NÃO significa 4.0 GHz ou que um sistema operacional de 32 bits não aproveita as vantagens do hardware de 64 bits.
O que me deixa triste é ouvir esse tipo de enganação picaretagem de amigos/conhecidos da faculdade ( Tecnologia em Informática com Ênfase em Gestão de Negócios – FATEC Rio Preto). By the way, não quero desmerecer a faculdade, pois devo muito à vários professores que tiveram a paciência de aguentar alunos como eu e o bomba.
Antes de entrar no assunto principal, entenda que não adianta ter um processador com 487564764 núcleos se o software não sabe como utilizá-los, okay?
Como recentemente adquiri um Phenom X3 (é, 3 núcleos) resolvi descobrir como aproveitar todo esse poder. Com uma busca aqui e uma ali (no oráculo), trago o que aprendi.
OpenMP?
O OpenMP (Open Multi-Processing) é uma API aberta para programação paralela. De acordo com o site oficial:
A API OpenMP auxilia na programação multiplataforma, paralela e com memória compartilhada em C/C++ e Fortran em todas as arquiteturas, incluindo plataformas Unix e Windows NT. Constituída por um grupo de grandes empresas de hardware e software, o OpenMP é um modelo portável e escalável que oferece ao programador uma interface flexível para o desenvolvimento de aplicações paralelas visando desktop até supercomputadores.
openmp.org
A tradução no olhômetro ficou um lixo, mas dá pra ter uma idéia do que se trata.
Beleza, nunca ouvi falar. Vale a pena alocar recursos (tempo) para aprender?
leitor angustiado
Saiba que essa API (pelo menos a especificação) existe desde 1997, sendo os membros permanentes do Architecture Review Board (ARB):
- AMD (David Leibs)
- Cray (James Beyer)
- Fujitsu (Matthijs van Waveren)
- HP (Uriel Schafer)
- IBM (Kelvin Li)
- Intel (Sanjiv Shah)
- NEC (Kazuhiro Kusano)
- The Portland Group, Inc. (Michael Wolfe)
- SGI (Lori Gilbert)
- Sun Microsystems (Nawal Copty)
- Microsoft (-)
Convencido(a)?
Instalando o OpenMP
É simples, você não instala.
Como assim?
leitor confuso
Você DEVE ter um compilador que tenha o OpenMP implementado.
E o meu compilador implementa?
leitor esperançoso
Aqui vc pode ver a lista de compiladores que disponibilizam o recurso. Como, provavelmente, vc usa:
- Visual C++ 2008: apenas a versão Professional (ou sei lá o nome da versão que não seja a Express) possui os headers necessários. ACHO que se vc copiar os headers da versão paga para a Express, irá funcionar;
- Code::Blocks (MinGW): apenas nas versões (do gcc) 4.3.2 ou superiores.
Baixei o MinGW mais recente no site oficial e instalei para usar com o Code::Blocks. Porém, a versão do gcc era a 3.4.alguma-coisa e é claro, não funcionou pois não possuia os headers necessários.
Então, resolvi instalar logo o TDM’s GCC/MinGW que é uma build não oficial dos binários mais recentes do GCC. Faça o download do instalador mais recente e, na hora da instalação, escolha o diretório MinGW que está dentro do diretório de instalação do seu Code::Blocks (no meu caso, E:\CodeBlocks\MinGW):
Hello World!
Se tudo estiver certo, então será possível compilar o “Hello World” abaixo:
#include <omp.h>
#include <stdio.h>
int main()
{
#pragma omp parallel
printf("Hello! (from thread %d, num. threads %d)\n",
omp_get_thread_num(),
omp_get_num_threads());
}
Antes de tentar rodar o exemplo, precisamos definir a compile-time flag -fopenmp para que o compilador saiba que o projeto utiliza o OpenMP. Se vc compilar pelo prompt de comando diretamente com o GCC, basta adicionar o parâmetro -fopenmp, ficando assim:
gcc.exe hello_world.c -o hello_world.exe -fopenmp
Já no Code::Blocks, vc também precisa linkar a libgomp.dll.a e ter o arquivo libgomp-1.dll na pasta BIN do seu compilador ou na pasta do seu projeto. Então, faça assim:
- Selecione a opção “Build options…” no menu “Project” do Code::Blocks;
- Na lista da esquerda, selecione o seu projeto (o 1º item, não o Debug, nem o Release);
- Procure a aba “Other options” dentro da aba “Compiler settings”. Adicione a flag -fopenmp;
- Agora selecione a aba “Linker settings” e adicione o arquivo libgomp.dll.a. Na minha instalação, esse arquivo estava no diretório “E:\CodeBlocks\MinGW\lib\gcc\mingw32\4.4.1\“;
- É importante que vc linke o arquivo libgomp.dll.a e não o libgomp.a;
- O projeto já pode ser compilado, mas para que funcione, será necessário copiar o arquivo libgomp-1.dll para o diretório do seu executável. Assim como a lib, o diretório em que esse arquivo pode ser encontrado não é tão trivial. Na minha instalação, encontrei em “E:\CodeBlocks\MinGW\lib\gcc\mingw32\bin“;
- Creio que não é necessário explicar a parte de copiar o arquivo (CTRL + C, CTRL + V, a mesma coisa que vc usa para fazer os trabalhos da faculdade).
Btw, GOMP é o projeto que implementou o OpenMP nos compiladores C, C++ e Fortran do GNU Compiler Collection.
Pronto, o Hello World deve (ou deveria) mostrar algumas mensagens “Hello!” com o ID da thread em que está sendo executado, seguido do número de threads.
Mas por que 3 threads? Porque esse é o número padrão para a variável ambiente OMP_NUM_THREADS (na minha implementação, pelo menos). Para definir o número de threads, chame a função omp_set_num_threads(num_threads). Então, o “Hello World” modificado ficaria assim:
#include <omp.h>
#include <stdio.h>
int main()
{
omp_set_num_threads(10);
#pragma omp parallel
printf("Hello! (from thread %d, num. threads %d)\n",
omp_get_thread_num(),
omp_get_num_threads());
}
Agora vc verá 10 mensagens “Hello!”.
É só isso?
Não. Apesar de simples, o exemplo anterior usa eficientemente todos os núcleos disponíveis, de forma transparente. Pode parecer que não houve um grande ganho no desempenho, mas com alguns testes vamos ver que a programação multicore pode otimizar de forma significativa o aplicativo.
Para que o post não fique cansativo, deixo o resto para semana que vem.
Fonte: OpenMP.org
0 Comments
1 Pingback