<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Silveira Neto &#187; mpirun</title>
	<atom:link href="http://silveiraneto.net/tag/mpirun/feed/" rel="self" type="application/rss+xml" />
	<link>http://silveiraneto.net</link>
	<description>the world is a pixel</description>
	<lastBuildDate>Sun, 08 Jan 2012 05:17:57 +0000</lastBuildDate>
	<language>pt-br</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.5</generator>
		<item>
		<title>Olá Mundo Paralelo com MPI</title>
		<link>http://silveiraneto.net/2007/08/29/ola-mundo-paralelo-com-mpi/</link>
		<comments>http://silveiraneto.net/2007/08/29/ola-mundo-paralelo-com-mpi/#comments</comments>
		<pubDate>Wed, 29 Aug 2007 13:53:12 +0000</pubDate>
		<dc:creator>Silveira</dc:creator>
				<category><![CDATA[português]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[CAD]]></category>
		<category><![CDATA[Computação Paralela]]></category>
		<category><![CDATA[hpc]]></category>
		<category><![CDATA[MPI]]></category>
		<category><![CDATA[mpicc]]></category>
		<category><![CDATA[mpirun]]></category>
		<category><![CDATA[OpenMPI]]></category>
		<category><![CDATA[Programação]]></category>
		<category><![CDATA[Troca de mensagens]]></category>

		<guid isPermaLink="false">http://silveiraneto.net/2007/08/29/ola-mundo-paralelo-com-mpi/</guid>
		<description><![CDATA[MPI é a sigla para Message Passing Interface, um padrão de comunicação de dados para computação paralela. O MPI oferece diversas abstracções que facilitam e padronizam o desenvolvimento de aplicações paralelas. Por exemplo, você pode programar para vários processadores, nós de um cluster, supercomputadores ou Internet utilizando a mesma infraestrutura transparentemente. Cluster Columbia da NASA, [...]]]></description>
			<content:encoded><![CDATA[<p>MPI é a sigla para <em>Message Passing Interface</em>, um padrão de comunicação de dados para computação paralela. O MPI oferece diversas abstracções que facilitam e padronizam o desenvolvimento de aplicações paralelas. Por exemplo, você pode programar para vários processadores, nós de um cluster, supercomputadores ou Internet utilizando a mesma infraestrutura transparentemente.</p>
<p><img src="http://silveiraneto.net/wp-content/uploads/2007/08/cluster_columbia_nasa.jpg" alt="Supercomputador Nasa" /><br />
<small>Cluster <a href="http://www.nas.nasa.gov/News/Images/columbia_3.html">Columbia da NASA</a>, com 1024 nós.</small></p>
<p>Como MPI é um padrão, existem vários padrões de implementação, abertas, fechadas, comerciais ou gratuitas. MPI é definido a princípio para C e Fortran, mas há implementações em outras linguagens como Java ou Python, por exemplo. A implementação que eu vou utilizar nesse exemplo é a <a href="http://www.open-mpi.org/">OpenMPI</a>.</p>
<p>A notícia boa é que você não precisa ter um supercomputador em casa para aprender e praticar computação paralela, uma máquina doméstica serve. Se você tiver uma máquina com múltiplos processadores, melhor ainda.</p>
<h3>Instalação</h3>
<p>Para instalar um ambiente de desenvolvimento para MPI no <a href="http://www.ubuntu.org">Ubuntu Linux</a> basta um comando:</p>
<blockquote><p>sudo apt-get install build-essential openmpi-dev</p></blockquote>
<p>Isso vai instalar um conjunto básico de compiladores e o ambiente OpenMPI.</p>
<h3>O código</h3>
<p>Vamos criar um arquivo chamado <em>ola.c</em> com o conteúdo:</p>
<div class="wp_syntax">
<div class="code">
<pre class="java java" style="font-family:monospace;">#include
#include
<span style="color: #000066; font-weight: bold;">int</span> size, rank;
<span style="color: #000066; font-weight: bold;">int</span> main<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">int</span> argc, <span style="color: #000066; font-weight: bold;">char</span> <span style="color: #339933;">*</span>argv<span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
   MPI_Init<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>amp;argc,<span style="color: #339933;">&amp;</span>amp;argv<span style="color: #009900;">&#41;</span>;
   MPI_Comm_size<span style="color: #009900;">&#40;</span>MPI_COMM_WORLD,<span style="color: #339933;">&amp;</span>amp;size<span style="color: #009900;">&#41;</span>;
   MPI_Comm_rank<span style="color: #009900;">&#40;</span>MPI_COMM_WORLD,<span style="color: #339933;">&amp;</span>amp;rank<span style="color: #009900;">&#41;</span>;
   printf<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Oi. Eu sou o processo %d de %d<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>, rank, size<span style="color: #009900;">&#41;</span>;
   MPI_Finalize<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
<span style="color: #009900;">&#125;</span></pre>
</div>
</div>
<h3>Compilação</h3>
<p>Para compilar esse código vamos usar o comando mpicc que foi instalado junto com o pacote openmpi-dev. Ele é uma interface para o gcc, e vai cuidar de toda a linkagem com as bibliotecas do MPI. Você pode usar os parâmetros do gcc com o mpicc.</p>
<blockquote><p>mpicc ola.c -o ola</p></blockquote>
<p>Se tudo der certo esse comando vai criar o binário ola.</p>
<h3>Execução</h3>
<p>Outra ferramenta importante é o mpirun, que levantar o mpi nos diversos nós e mandar cada nó executar o binário. O mpirun não precisa de um programa mpi para rodar, por exemplo, se dermos esse comando:</p>
<blockquote><p>mpirun -np 4 echo oi</p></blockquote>
<p>Você vai ter essa saída:</p>
<blockquote><p>oi<br />
oi<br />
oi<br />
oi</p></blockquote>
<p>Você mandou 4 nós (<em>-np 4</em>) executar o comando <em>echo oi</em> (imprime oi). Para mandar 5 nós executarem nosso binário ola:</p>
<blockquote><p>mpirun -np 5 ola</p></blockquote>
<p>E vamos ter uma saída mais ou menos assim:</p>
<blockquote><p>Oi. Eu sou o processo 1 de 5<br />
Oi. Eu sou o processo 4 de 5<br />
Oi. Eu sou o processo 0 de 5<br />
Oi. Eu sou o processo 2 de 5<br />
Oi. Eu sou o processo 3 de 5</p></blockquote>
<p>Por que as saídas sairam desordenadas? Porque elas rodaram em paralelo e não temos como saber qual foi sua ordem de execução. Assim cada nó entrou no printf em um momento diferente e imprimiu seu <em>rank</em> e seu <em>size</em> naquele momento. Você pode experimentar usar o parâmetro -np com outros números maiores ou menores que 5.</p>
<h3>Troca de Mensagens</h3>
<p>Até aqui não há muita graça porque não há troca de mensagens. Há muito o que se dizer sobre como trocar mensagens do MPI mas a maneira mais fácil de se começar é com a função <em>mpi_send</em>.</p>
<p>Vamos fazer um programa bem simples onde o nó 0 vai mandar uma mensagem para o nó 1. A mensagem vai ser um número, <a href="http://desciclo.pedia.ws/wiki/42">42</a>. Criemos um arquivo chamado msg.c com o código:</p>
<div class="wp_syntax">
<div class="code">
<pre class="java java" style="font-family:monospace;">#include
#include
&nbsp;
<span style="color: #000066; font-weight: bold;">int</span> size, rank, msg, source, dest, tag;
&nbsp;
<span style="color: #000066; font-weight: bold;">int</span> main<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">int</span> argc, <span style="color: #000066; font-weight: bold;">char</span> <span style="color: #339933;">*</span>argv<span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
   MPI_Status stat;
&nbsp;
   MPI_Init<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>amp;argc,<span style="color: #339933;">&amp;</span>amp;argv<span style="color: #009900;">&#41;</span>;
   MPI_Comm_size<span style="color: #009900;">&#40;</span>MPI_COMM_WORLD,<span style="color: #339933;">&amp;</span>amp;size<span style="color: #009900;">&#41;</span>;
   MPI_Comm_rank<span style="color: #009900;">&#40;</span>MPI_COMM_WORLD,<span style="color: #339933;">&amp;</span>amp;rank<span style="color: #009900;">&#41;</span>;
&nbsp;
	<span style="color: #000000; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span>rank<span style="color: #339933;">==</span>0<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
   	msg <span style="color: #339933;">=</span> <span style="color: #cc66cc;">42</span>; dest <span style="color: #339933;">=</span> <span style="color: #cc66cc;">1</span>; tag <span style="color: #339933;">=</span> 0;
   	MPI_Send<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>amp;msg, <span style="color: #cc66cc;">1</span>, MPI_INT, dest, tag, MPI_COMM_WORLD<span style="color: #009900;">&#41;</span>;
   	printf<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Processo %d enviou %d para %d.<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>, rank, msg, dest<span style="color: #009900;">&#41;</span>;
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span>rank<span style="color: #339933;">==</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		source <span style="color: #339933;">=</span> 0; tag <span style="color: #339933;">=</span> 0;
		MPI_Recv<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>amp;msg, <span style="color: #cc66cc;">1</span>, MPI_INT, source, tag, MPI_COMM_WORLD, <span style="color: #339933;">&amp;</span>amp;stat<span style="color: #009900;">&#41;</span>;
		printf<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Processo %d recebeu %d de %d.<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>, rank, msg, source<span style="color: #009900;">&#41;</span>;
	<span style="color: #009900;">&#125;</span>
&nbsp;
   MPI_Finalize<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
<span style="color: #009900;">&#125;</span></pre>
</div>
</div>
<p>No processo de rank 0 vamos enviar o conteúdo da variável inteira msg para o processo de rank 1. Note que no processo de rank 1, o valor de msg não está definido. O comando MPI_Send vai receber 6 parâmetros.</p>
<blockquote><p>int MPI_Send( void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm)</p></blockquote>
<ul>
<li><strong>void *buf</strong>, um ponteiro para a mensagem que você vai mandar. No nosso caso a variável inteira msg.</li>
<li><strong>int count</strong>, a quantidade de elementos que tem nessa mensagem. No nossa caso só 1. Se quisemos mandar um vetor de dois inteiros, seria 2.</li>
<li><strong>MPI_Datatype datatype</strong>, uma constante que define o tipo de dados que você está enviando. No nosso caso MPI_INT. Isso evita que ajam incompatibilidade no tamanho de inteiros entre arquiteturas diferentes.</li>
<li><strong>int dest</strong>, o rank do nó destino, o destinatário. No nosso caso o nó 1.</li>
<li><strong>int tag</strong>, a tag seria num email o assunto da mensagem. Estamos mandando tag 0 então no outro lado tem que estar esperando uma tag 0, caso contrário não há comunicação.</li>
<li><strong>MPI_Comm comm</strong>, o comunicador. Nesse e na maioria dos casos  a constante MPI_COMM_WORLD.</li>
</ul>
<p>Do outro lado, no processo 1 vamos usar o MPI_recv, que recebe 7 parâmetros.</p>
<blockquote><p>int MPI_Recv( void *buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Status *status)</p></blockquote>
<ul>
<li><strong>void *buf</strong>, um ponteiro para onde vai ser guardada a mensagem que vamos receber. No nosso caso a variável msg, que no processo 1 está vazia.</li>
<li><strong>int count</strong>, a quantidade de elementos que vem nessa mensagem.</li>
<li><strong>MPI_Datatype datatype</strong>, a mesma constante do MPI_send.</li>
<li><strong>int source</strong>, o rank do nó remetente. No nosso caso o nó 0.</li>
<li><strong>int tag</strong>, a tag da mensagem conforme explicado no MPI_send.</li>
<li><strong>MPI_Comm comm</strong>, o comunicador.</li>
<li><strong>MPI_Status *status</strong>, uma estrutura para que depois que a função for executada você possa inspecionar detalhes da transmissão. No nosso caso ela é inútil.</li>
</ul>
<p>Para compilar esse exemplo usamos novamente o mpicc.</p>
<blockquote><p>mpicc msg.c -o msg</p></blockquote>
<p>E para executa-lo o mpirun.</p>
<blockquote><p>mpirun -np 2 msg</p></blockquote>
<p>O programa vai escrever essa mensagem:</p>
<blockquote><p>Processo 0 enviou 42 para 1.<br />
Processo 1 recebeu 42 de 0</p></blockquote>
<p>No processo 1 a msg estava inicialmente vazia e no processo 0 havia 42, mas depois do MPI_recv o processo 1 pode escrever o conteúdo 42 de msg. Logo, houve comunicação.</p>
<h3>Dicas</h3>
<p>Por um problema no empacotamento do mpich no Ubuntu toda vez que você executa o MPI você recebe umas mensagens horrorosas de erro, que na verdade são só um aviso que ele não encontrou uma placa de rede Infiniband.</p>
<p>Para você silenciar na unha essa chatice use o mpirun assim:</p>
<blockquote><p>mpiexec &#8211;mca btl ^openib -np 1 executável</p></blockquote>
<p>Onde -np 1 deve ser substituido pelo seu número de processos e executável pelo seu executável.</p>
<p>Outra dica é que você pode utilizar uma distribuição Linux que já venha com o MPI instalado. Por exemplo o<a href="https://www.scientificlinux.org/download"> Scientific Linux</a> ou o <a href="http://pareto.uab.es/mcreel/ParallelKnoppix/">Parallel Knoppix</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://silveiraneto.net/2007/08/29/ola-mundo-paralelo-com-mpi/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>

