UNIVERSIDADE ESTADUAL DO CEARÁ Programação Paralela e Concorrente Felipe de Almeida Xavier João Gonçalves Filho Prof.: Marcial Porto Fernandez FORTALEZA 2011
Sumário 1 Manual de Instalação 2 1.1 Programa Versão 1........................ 2 1.2 Programa Versão 2........................ 2 2 Babuínos cruzando um cânion 3 2.1 Descrição do Problema...................... 3 2.2 Interface Gráfica 1........................ 4 2.3 Interface Gráfica 2........................ 4 2.4 Estatísticas............................ 4 2.5 Estrutura............................. 5 3 Política Utilizada 6 4 Divisão de Tarefas 7 1
1 Manual de Instalação Para implementação foi utilizado a linguagem C++ com compilador g++4.6.1, então se faz necessário ter o compilador g++ instalado na máquina para poder recompilar o programa e gerar o executável que funcione na arquitetura do seu computador.já para parte gráfica foi usada a biblioteca SDL que feita também para C/C++, logo é preciso instalar os pacotes para que o programa posso ser instalado e executado. Se você possui na sua máquina o gerenciador de pacote apt get ou o Y um, você pode instalar os pacotes utilizando os seguintes comandos: apt get install libsdl1.2-dev libsdl-image1.2-dev libsdl-mixer1.2-dev libsdl-ttf2.0-dev yum install SDL-devel SDL mixer-devel SDL image-devel SDL ttf-devel Caso não possua um desses gerenciadores você precisa baixar a biblioteca do SDL através desse link: http://www.libsdl.org/download-1.2.php. Os pacotes do programa você encontra nos seguintes links: http://jeri.larces.uece.br/~joaogf/babuinopipe.zip http://jeri.larces.uece.br/~joaogf/babuinoex.tar 1.1 Programa Versão 1 Quando for extraído os arquivos será gerado um arquivo conf igure.sh,é necessário dar permissão para execução desse arquivo, para isso use o seguinte comando: $ chmod +x configure.sh Então executamos o configure, que vai compilar o código do programa e irá gerar uma pasta chamada programa, dentro dessa pasta estão todos os arquivos que o programa vai precisar para executar. Nessa versão foi usado o pipeline, para rodar o programa basta executar o script main.sh que irá rodar os dois binários que estão na pasta bin. 1.2 Programa Versão 2 É semelhante ao programa versão 1, após o configure, rode o script main.sh, mas nesse caso apenas o binário babuino é executado, pois nessa versão não foi usado o pipeline. Para ambas as versões existe um arquivo 2
chamado input.babu na pasta input, onde poderá ser setado alguns parâmetros do programa, são eles o número de babuínos, tempo de espera entre babuínos e número máximo de babuínos simultâneos da mesma direção que não irão dar a vez para os do outro lado. 2 Babuínos cruzando um cânion 2.1 Descrição do Problema Um estudante graduando em antropologia e em ciência da computação embarcou em um projeto de pesquisa para ver se os babuínos africanos tem inteligência para superar impasses (deadlocks). Ele localiza um cânion profundo e prende uma corda através dele, assim os babuínos podem cruzá-lo utilizando a corda. A passagem ao longo da corda segue estas regras: Vários babuínos podem atravessar o cânion ao mesmo tempo, desde que todos estejam indo no mesmo sentido. Babuínos se movendo em sentidos contrários irão produzir um impasse (os babuínos ficarão presos no meio da corda), porque é impossível para um babuíno passar sobre o outro, enquanto estiver suspenso sobre o canyon. Estando no meio da corda os babuínos também não sabem voltar. Quando um babuíno for atravessar o cânion, ele deve verificar se nenhum outro babuíno está atravessando no sentido oposto (deve esperar até a corda ficar livre). Implementação de uma solução que evita a fome (starvarion). Se um número grande de babuínos chegar em um lado do cânion, deve ser implementada uma política para permitir que os babuínos no sentido contrário possam atravessar. (alternar a oportunidade de travessia) A travessia também deve ser otimizada para evitar esperas muito longas (vários babuínos atravessando ao mesmo tempo). Fonte: http://marcial.larces.uece.br/cursos/programacao-concorrente-e-paralela-2011- trabalho-pratico-2011-2 3
2.2 Interface Gráfica 1 Para implementar o trabalho descrito, elaboramos primeiramente uma simulação sem interface gráfica alguma, com o objetivo de testar os resultados mais rapidamente afim de evitar deadlocks. Quando terminamos e vimos que tinhamos resolvido o problema para o starvation, decidimos então desenvolver a parte gráfica separada. Assim, utilizamos o pipeline para a comunição entre os processos: o controle do babuínos sem starvation(processo 1) e a parte gráfica responsável por ilustrar a travessia dos babuínos(processo 2). Temos então, para a interface gráfica 1, comandos obtidos pela saída padrão do processo 1 para controlar a passagem dos babuínos pela ponte graficamente. Foram encontrados dois problemas nessa abordagem. O primeiro foi devido ao fato de utilizarmos o comando cout da biblioteca iostream para jogar os comandos na saída padrão e ainda o flush para forçar a saída. No entanto, como tinhamos threads rodado no processo 1 que executavam o flush, o flush de uma thread era executado no momento em que o cout de outra ainda estava em execução. Isso fez com que os comandos passados para o processo 2 fossem incompreensíveis, causando resultados inesperados na interface gráfica. O problema não foi muito comum de acontecer durante os nossos testes. Esse problema pode ser resolvido com uso de mutex para quem fosse imprimir algo na saída padrão. O segundo Problema foi devido à sincronização entre os processos. Os babuínos na interface gráfica ficavam esperando os comandos do processo 1 para dar continuidade à travessia, por exemplo, se o babuíno poderia entrar na ponte ou não. 2.3 Interface Gráfica 2 Para tentar uma outra solução, resolvemos implementar o problema como um processo único e todo o controle ocorria somente nele. As mesmas funções lançadas na thread foram aproveitadas da solução anterior mostrada. As modificações ocorreram nos métodos responsáveis por imprimir os babuínos na tela e como adaptar os comandos pelo fato de não receber nessa versão os camandos do processo 1. 2.4 Estatísticas São informados três dados importantes como resultado do trabalho: A quantidade de babuínos para cada sentido. 4
O tempo médio de espera para atravessar (tempo de espera + travessia). A taxa de aproveitamento da corda (tempo em uso / tempo total). A quantidade de babuínos para cada sentido foi obtida através do método que gerava os babuínos. Com 50% de chances de aparecer um babuíno da direita ou da esquerda, existe um contador calculando a quantidade de babuínos da esquerda, a quantidade dos da direita é obtida subtraindo-se do total de babuínos os gerados pela esquerda. BD = T OT AL B BE Para o valor do tempo médio de espera da atravessia, foi capturado o tempo corrente no momento antes em que o babuíno checa se a ponte está desponível e o outro no instante em que ele está livre para passar. É feita a subtração do último com primeiro e o resultado somado ao tempo de travessia de 4 segundos. A taxa de aproveitamento da corda é calculado obtendo os dois tempos: tempo total disponível da corda e tempo de uso da corda. O tempo total disponível da corda é obtido subtraindo o tempo corrente no início do programa do tempo corrente em que o último babuíno termina de atravessar. T D = T F T I. Foi utilizado a função gettimeofday() da biblioteca sys/time.h para a captura de ambos os tempos; 2.5 Estrutura 1 { 2 /* Semaforo de controle dos Babuinos vindos da direita */ 3 Semaphore right ; 4 /* Semaforo de controle dos Babuinos vindos da esquerda */ 5 Semaphore left ; 6 /* Estados da ponte */ 7 /* Ponte livre */ 8 # define ENABLE 1 9 /* Babuinos vindos da esquerda estao atualmente atravessando a ponte */ 10 # define RIGHTDISABLE 3 11 /* Babuinos vindos da direita estao atualmente atravessando a ponte */ 12 # define LEFTDISABLE 2 13 /* Exclusao mutua para acessar a condicao da ponte */ 14 Semaphore brg ; 15 /* funcoes threads */ 16 void * control ( void * arg ); 17 void * monkey ( void * arg ); 18 void * generate ( void * arg ); 5
19 void * calcs ( void * arg ); 20 } No código acima temos as principais variáveis e funções usadas para criar o programa. generate: Essa função irá simplesmente criar as threads monkey e setar o atributo direção do babuíno como direito ou esquerdo, isso é escolhido de forma aleatória. O tempo de criaçãos das threads monkey é definido no arquivo input.babu calcs: Essa função fica constantemente fazendo os cálculos das estatísticas para serem analisadas no final da execução. monkey e control Quando um monkey é criado ele deve saber se é possível o acesso a ponte, para isso ele testa o seu semafóro right/left. Esses semáforos recebem up() na função control, esta função sabe se deve ou não permitir um babuíno passar, analisando a condição atual da ponte. Suponha que a ponte está ENABLE, então o control permite acesso à um babuíno direito, logo ele seta a condição da ponte para LEF T DISABLE que quer dizer que apenas babuínos direitos podem passar pela ponte. A ponte volta a ficar ENABLE quando a fila de babuínos que estão atravessando a ponte está vazia, isso é analisado e setado na função monkey. 3 Política Utilizada Possíveis políticas de comportamento dos babuínos para este trabalho seriam: a Política Justa, a Política Comum e a Política de Controle de Starvation. A Política Justa é aquela em que segue a ordem de uma fila de chegada de babuínos. Ao chegar um babuíno quando a ponte está ocupada por outro do mesmo sentido, ele só aproveitará para passar se já não estiver um outro babuíno esperando no sentido oposto, obedecendo a ordem de chegada de cada babuíno. A Política Comum é aquela sitada no começo da descrição do trabalho, no qual ao chegar um babuíno e a ponte estiver ocupada no mesmo sentido de permissão, ele entrará também na ponte independentemente se ouver ou não um outro babuíno na direção oposta. A Política de Controle de Starvation é a política que tende ser a mais eficiente. É a política implementada neste trabalho, e somente. Ela é a aquela que procura ser justa com ambos os lados, sendo que o babuíno que 6
chegar no sentido oposto ao de permissão da ponte, só vai ficar esperando até o terceiro babuíno que atravessar (numero escolhido pela equipe), ganhando em seguida a permissão da ponte e evitando que babuínos da direção oposta se aproveitem e ocasione espera indefinida pelo que está esperando. A implementação da Política de controle de Starvation foi feita na thread control que ficou responsável por checar se o babuíno que está esperando já pode ter acesso à ponte, bloqueando-a para o lado oposto. O controle é feito por meio de uma fila que armazena o sentido de cada babuíno que chega. Possibilitando à ele conhecer o sentido dos babuínos criados e dar acesso ao babuíno segundo à política. 4 Divisão de Tarefas Inicialmente o Felipe implementou uma versão sem interface gráfica, durante os testes foi detectado deadlock. Em seguida, os dois planjeram uma outra solução com a política de controle de starvation, que é a utilizada agora, ambos implementaram a nova abordagem sem interface gráfica, onde o João concluiu o controle de starvation e o Felipe as estatísticas. Na parte gráfica, o João acrescentou o cenário com macaquinhos passando na ponte e o Felipe mostrou o resultado das estatísticas ao final da execução. 7