Differences
This shows you the differences between the selected revision and the current version of the page.
ipar:modelo 2007/11/19 17:19 | ipar:modelo 2007/12/24 17:45 current | ||
---|---|---|---|
Line 1: | Line 1: | ||
+ | ===== Descrição do modelo de paralelização ===== | ||
- | **Programa a ser paralelizado** | + | O framework **ipar** foi desenvolvido em Java com o objetivo de controlar a distribuição de tarefas em aplicações paralelas de alto desempenho. Seu modelo foi desenvolvido tendo como foco plataformas tipo cluster que utilizem sistema operacional Linux sistema de arquivos compartilhado (NFS). O modelo inicial do framework **ipar** utiliza o modelo de paralelismo Bag-of-Tasks. |
- | Deve ter 3 métodos: inicia(); finaliza(); executa(parametros) | + | Aplicações Bag-of-Tasks são aplicações paralelas cujo resultado final pode ser obtido particionando-se o problema em tarefas independentes. Este modelo apesar de simples, é muito utilizado em várias áreas. |
- | O programa deve ter um main que recebe parâmetros (strings). O primeiro parametro será sempre a string rmi usada para conexão com o gerente (Naming.rebind(string)) e o segundo um dos métodos citados acima. | ||
- | O método "executa" é o único que recebe parametros e pode ser utilizado para qualquer coisa de acordo com seus parametros. Pode ser usado até mesmo para chamar outros métodos a partir dele. | + | ===== O framework ===== |
- | Qualquer um dos métodos acima, após concluir sua computação, deve fazer uma conexão rmi retornando os resultados de suas computações para o gerente. Apenas uma conexão rmi deve ser realizada por cada computação e após ela ser feita o programa deve ser finalizado. | + | O **ipar** gerencia a chamada de tarefas em nodos do cluster segundo uma lista criada pela aplicação a ser paralelizada (esta será chamada de apenas de aplicação no decorrer do texto). A aplicação consiste de um programa escrito em Java que deve seguir uma estrutura bem definida. Quando o ipar é iniciado, este executa um shell script que deve conter a chamada do clall da aplicação que tiver a função main. Esta estrutura será descrita na seção //Aplicação a ser paralelizada//. |
- | //inicia()// | ||
- | Realiza rotinas iniciais do programa e cria as tarefas na forma de strings que serão posteriormente passadas para o executa | + | ==== Estrutura Básica ==== |
- | Retorno do rmi: | + | Tem uma estrutura básica organizada da seguinte forma: |
- | deve retornar uma lista de strings onde cada string é uma tarefa a ser computada usando a seguinte estrutura: | + | |
- | Boolean status = h.listaTarefas(string []listaTarefas); | + | |
- | este método rmi ("listaTarefas") pode ser chamado a qualquer momento adicionando novas tarefas. | + | Tem uma lista com os nodos a serão utilizados, que é passada como parâmetro de entrada. Sendo o primeiro da lista o nodo onde o gerente está rodando. |
- | //finaliza()// | + | //Lista de nodos//: é um Vector Vectror. Cada posição do Vector "pai" representa um nodo (Vector filho). O Vector filho possui dois elementos: |
- | Conclui o programa juntando todos os resultados das computações | + | * elemento 1: String: host do nodo |
- | Retorno do rmi: | + | * elemento 2: Byte: status do nodo (0: aguardando; 1: processando) |
- | informa a conclusão do programa chamando o seguinte método rmi: | + | |
- | Boolean status = h.finaliza(true); | + | |
- | //executa(parametros)// | + | //Lista de Tarefas//: é um vector em que cada elemento é outro vector. No vector principal ("pai"), cada indice corresponde a uma tarefa a ser executada e no vector interno ("filho" - cada indice do vector principal), tem três elementos: |
- | Executa uma determinada tarefa, os parâmetros são passados via linha de comando como string. O primeiro parametro passado é a id da tarefa e deve ser usada no retoro na resposta rmi e no nome dos arquivos com resultados parciais das computações, se necessário. Os demais podem ser usados livremente. Como os parãmetros são sempre string, pois são passagens de argumento, devem ser convertidos para os tipos de dados desejados. | + | * elemento 1: tipo String - corresponde a tarefa. Será passada para o executa quando a tarefa for distribuída |
- | + | * elemento 2: tipo byte - corresponde ao status da tarefa. | |
- | Retorno do rmi: | + | * Valor 0: aguardando |
- | deve retornar o id da tarefa e o seu status ou redistribui em novas tarefas. Se a tarefa foi concluída com exito o parâmetro é true se não o parâmetro é false | + | * Valor 1: processando |
+ | * Valor 2: finalizada | ||
- | Boolean status = h.tarefa(int, tarefa, boolean status); | + | * elemento 3: id do nodo que esta processando a tarefa, que é o índice do Vector "pai" da lista de nodos |
- | Boolean status = h.listaTarefas([]listaTarefas); | + | * elemento 4: tipo tempo - tempo de inicio da tarefa |
- | no caso de redistribuíção de tarefas será subentendido que a tarefa foi concluída com exito e foi quebrada em outras subtarefas | + | * elemento 5: tipo tempo - tempo gasto na realização da tarefa |
- | + | ||
- | O que pode ser uma tarefa: | + | |
- | Um exemplo de tarefa seria uma figura ao qual deve ser aplicado um algorítmo. Portanto o método "inicia" pode particionar uma determinada imagem em várias subimagens para poder computar cada uma em um nodo diferente. Desta maneira o nome de cada subimagem pode ser a tarefa, logo quando o "gerente" distribuir as tarefas ele vai passar o seu nome para o método executa. depois de todas as tarefas terem sido executadas, o método "finaliza" é chamado para computar os resultados parciais que devem obrigatóriamente estarem armazenados em arquivos. | + | O identificador da tarefa é o próprio indice do vector principal. |
- | **O programa gerente:** | + | Este vector é prenchido em tempo de execução quando for chamado o método rmi "listaTarefas([]listaTarefas)". **Deve** ser chamado no início do programa a ser paralelizado(método "inicia()") e **pode** ser chamado pelo método "executa(parametros)" |
- | Controla a distribuíção das tarefas nos nodos. | + | De tempos em tempos este vector com as tarefas deve ser gravado em arquivo para que se possa monitorar o status do processamento |
- | Tem uma lista com os nodos a serão utilizados, que é passada como parâmetro de entrada. Sendo o primeiro da lista o nodo onde o gerente está rodando. | + | ==== Algorítmo: ==== |
- | cria uma lista de nodos | + | início |
- | Tem um vector em que cada elemento é outro vector: | + | * start do servidor rmi |
+ | * chamada do método "inicia" (pode ser no nodo local ou em outro) | ||
+ | * aguarda a conexao rmi para informar a lista de tarefas | ||
+ | * monta a lista de tarefas | ||
+ | * inicio do escalonador para distribuir as tarefas | ||
+ | * verifica se tem nodo livre | ||
+ | * se tem, varre lista de tarefas a procura de uma tarefa a ser distribuída | ||
+ | * se encontra tarefa, encaminha para o nodo disponível (chama vis rsh um script rum_cliente que deve chamar do metodo "executa" do programa a ser paralelizado.), muda o status do nodo para processando e atribui o id do nodo a tarefa | ||
+ | * quando todas as tarefas forem finalizadas, chama o metodo "finaliza" do programa a ser paralelizado. | ||
- | No vector principal, cada indice corresponde a uma tarefa a ser executada | ||
- | No vector interno (cada indice do vector principal), tem tres elementos: | + | ===== Aplicação a ser paralelizada ===== |
- | elemento 1: tipo String - corresponde a tarefa. Será passada para o executa quando a tarefa for distribuída | + | Deve ter no mínimo 3 métodos: //inicia(); finaliza(); executa(parametros)// |
- | elemento 2: tipo byte - corresponde ao status da tarefa. | + | O programa deve ter um main que recebe parâmetros (strings). O primeiro parametro será sempre a string rmi usada na conexão com o gerente (Naming.rebind(string)) e o segundo um dos métodos citados acima. |
- | Valor 0: aguardando | + | O método "executa" é o único que recebe parâmetros e pode ser utilizado para qualquer coisa de acordo com seus parâmetros. Pode ser usado até mesmo para chamar outros métodos a partir dele. Este método é contém o código paralelizado. |
- | Valor 1: processando | + | Qualquer um dos métodos acima, após concluir sua computação, deve fazer uma conexão rmi retornando os resultados de suas computações para o gerente. Apenas uma conexão rmi deve ser realizada por cada computação, e após ela ser feita o programa deve ser finalizado. |
- | Valor 2: finalizada | + | ==== Descrição dos métodos ==== |
- | elemento 3: id do nodo que esta processando a tarefa | + | **Método //inicia()//** |
- | elemento 4: tipo tempo - tempo de inicio da tarefa | + | Realiza rotinas iniciais do programa e cria as tarefas na forma de strings que serão posteriormente passadas para o método "executa". |
- | elemento 5: tipo tempo - tempo gasto na realização da tarefa | + | __Retorno do rmi__: deve retornar uma lista de strings onde cada string é uma tarefa a ser computada usando a seguinte estrutura: |
- | O identificador da tarefa é o próprio indice do vector principal. | + | //Boolean status = h.listaTarefas(string []listaTarefas);// |
- | Este vector é prenchido em tempo de execução quando for chamado o metodo "inicia" do programa a ser paralelizado. | + | Este método rmi ("listaTarefas") pode ser chamado a qualquer momento (no método "executa") adicionando novas tarefas. |
- | De tempos em tempos este vector com as tarefas deve ser gravado em arquivo para que se possa monitorar o status do processamento | + | **Método //finaliza()//** |
- | Algorítmo: | + | Conclui o programa juntando todos os resultados das computações. |
- | início | + | __Retorno do rmi__: informa a conclusão do programa chamando o seguinte método rmi: |
- | start do servidor rmi | + | |
- | chamada do método "inicia" (pode ser no nodo local ou em outro) | + | |
- | aguarda a conexao rmi para informar a lista de tarefas | + | |
- | monta a lista de tarefas | + | |
- | inicio do escalonador para distribuir as tarefas | + | //Boolean status = h.finaliza(true);// |
- | verifica se tem nodo livre | + | |
- | se tem, varre lista de tarefas a procura de uma tarefa a ser distribuída | + | |
- | se encontra tarefa, encaminha para o nodo disponível (chama vis rsh um script rum_cliente que deve chamar do metodo "executa" do programa a ser paralelizado.), muda o status do nodo para processando e atribui o id do nodo a tarefa | + | |
- | quando todas as tarefas forem finalizadas, chama o metodo "finaliza" do programa a ser paralelizado. | + | **Método //executa(parametros)//** |
+ | Executa uma determinada tarefa, os parâmetros são passados via linha de comando como string. Os parâmetros passado devem obedecer a seguinte ordem: | ||
+ | * Parâmetro 1: id da tarefa e deve ser usada no retoro na resposta rmi e no nome dos arquivos com resultados parciais das computações, se necessário; | ||
+ | * Demais Parâmetros: Os demais podem ser usados livremente. Como os parâmetros são sempre string, pois são passagens de argumento, devem ser convertidos para os tipos de dados desejados. | ||
+ | __Retorno do rmi:__ deve retornar o id da tarefa e o seu status, ou redistribui a tagefa recebida em novas tarefas. Se a tarefa foi concluída com exito, o parâmetro é true se não o parâmetro é false: | ||
- | Modelo de implementação do Programa a ser paralelizado. | + | //Boolean status = h.tarefa(int, tarefa, boolean status);// |
- | cada método será chamado pelo programa gerente separadamente, portanto não compartilham variáveis eles tem que ser visualizados como programas diferentes rodando em momentos diferentes, portanto dados devem ser trocados através de arquivos. cada método pode ser desdobrado em outros conforme a necessidade do algoritmo, mas apenas estes serão chamados diretamente pelo programa "gerente" | + | ou |
+ | |||
+ | //Boolean status = h.listaTarefas([]listaTarefas);// | ||
+ | |||
+ | No caso de redistribuíção de tarefas será subentendido que a tarefa foi concluída com exito e foi quebrada em outras subtarefas. | ||
+ | |||
+ | ==== O que pode ser uma tarefa ==== | ||
+ | |||
+ | Um exemplo de tarefa seria uma figura ao qual deve ser aplicado um algorítmo. Portanto o método "inicia" pode particionar uma determinada imagem em várias subimagens para poder computar cada uma em um nodo diferente. Desta maneira o nome de cada subimagem pode ser a tarefa, logo quando o "gerente" distribuir as tarefas ele vai passar o seu nome para o método executa. depois de todas as tarefas terem sido executadas, o método "finaliza" é chamado para computar os resultados parciais que devem obrigatoriamente estarem armazenados em arquivos. | ||
+ | |||
+ | |||
+ | ==== Modelo de implementação do Programa a ser paralelizado ==== | ||
+ | |||
+ | |||
+ | Cada método será chamado pelo programa gerente separadamente, portanto não compartilham variáveis eles tem que ser visualizados como programas diferentes rodando em momentos diferentes, portanto dados devem ser trocados através de arquivos. cada método pode ser desdobrado em outros conforme a necessidade do algoritmo, mas apenas estes serão chamados diretamente pelo programa "gerente". | ||
Line 232: | Line 244: | ||
</code> | </code> | ||
- | |||