• Nenhum resultado encontrado

4.3 Metaheurísticas aplicadas ao problema do escalonamento de tarefas

4.3.1 Algoritmos genéticos aplicados ao escalonamento de tarefas

Por serem métodos probabilísticos e não exigirem muito conhecimento sobre os problemas para os quais são aplicados, os algoritmos genéticos são freqüentemente utilizados na tentativa de solucionar problemas complexos de otimização e aprendizado computacional. Em [89] foi realizado um estudo comparativo de algoritmos genéticos aplicados ao problema de escalonamento, utilizando-se duas abordagens distintas, onde foram testados diferentes maneiras de inicialização da população, função de avaliação, método de seleção, crossover (cruzamento), mutação e condição de término do AG. Nesta seção, como exemplo de aplicação de AGs para o problema do escalonamento de tarefas em multiprocessadores, descrevemos uma dessas abordagens.

O grafo de programa utilizado nos experimentos foi o Gauss18 (Figura 4.2) e uma arquitetura composta por dois processadores. Para a representação do problema (indivíduo) foi utilizada uma matriz dupla (2x18), onde são listadas cada tarefa e o processador (0 ou 1) nos quais elas estão alocadas. A Figura 4.12 ilustra dois exemplos de indivíduos.

Para a inicialização da população do AG, os indivíduos foram gerados aleatoriamente, sempre garantindo que cada tarefa aparecerá uma única vez no indivíduo, respeitando-se as restrições de pre- cedência impostas pelo grafo de programa. Para cada tarefa também foi realizado o sorteio aleatório do processador ao qual ela estaria alocado, no caso, o processador 0 ou 1. Para se validar as restrições de precedência, a seguinte estratégia foi utilizada: para cada tarefa sorteada, verifica-se se as tarefas precedentes à sua execução já fazem parte do indivíduo. Caso esta condição tenha sido satisfeita, a tarefa passa a compor o indivíduo e é retirada da “lista” de tarefas a serem sorteadas. Caso contrário, a tarefa é descartada para este sorteio, mas continua sendo uma tarefa possível de ser selecionada. O sorteio de tarefas é feito até que o indivíduo esteja completo, ou seja, todas as tarefas alocadas.

A aptidão (fitness) do indivíduo é o tempo de execução das tarefas, seguindo a distribuição das tarefas entre os processadores e a ordem de execução em cada processador, ambas representadas no indivíduo. Por exemplo, são gastas 4 unidades de tempo na execução da tarefa 4. Caso a tarefa 4 e a tarefa 9 estejam alocadas em processadores diferentes, após o término da tarefa 4, a tarefa 9 deverá aguardar 8 unidades de tempo para iniciar sua execução. Caso eles estejam alocadas no mesmo processador, a tarefa 9 poderá, após o término da tarefa 4, imediatamente ser executada.

O método de seleção conhecido como Torneio Simples foi utilizado. Além da simplicidade de implementação, a escolha deste método foi feita pelo fato dele apresentar uma baixa pressão seletiva. Métodos com uma maior pressão seletiva poderiam causar um convergência prematura da população, uma vez que a formação da população inicial utiliza um critério extremamente direcionado na geração do indivíduo. Neste torneio, três indivíduos da população são sorteados aleatoriamente, e o de menor fitness (menor tempo de execução das tarefas) é selecionado para participar de um par de pais do

crossover. O indivíduo vencedor de um torneio é retirado e não participa da seleção do segundo pai. Para realizar o cruzamento (crossover) entre os indivíduos pais selecionados, o método utilizado foi o Crossover Cíclico, que previne a existência de tarefas duplicadas no indivíduo, conforme apre- sentado na Figura 4.10. No indivíduo Pai 1, sorteia-se uma posição, e a tarefa nesta posição é passada para a mesma possição no novo indivíduo, o Filho 2. Para garantir que não haja repetição de tarefas nestes novos indivíduos, identifica-se no Pai 2 a tarefa que foi selecionada no Pai 1 e transfere-se esta para o Filho 1, na mesma posição em que foi encontrada, formando-se assim um ciclo, onde todos os genes dentro deste ciclo são transferidos da mesma maneira. Os genes que permanecem fora deste ciclo são copiados do Pai 1 e Pai2 para as mesmas posições nos filhos Filho 1 e Filho 2, respecti- vamente. Esse processo é aplicado considerando-se apenas as tarefas que compõem os indivíduos. Os processadores, de forma geral, acompanham as tarefas às quais estavam associados. Eventual- mente, pode ocorrer uma mutação (alteração do processador), provocando uma maior “perturbação” no indivíduo.

Após realizado o cruzamento, o operador genético utilizado é a Mutação. O processo utilizado foi a Permutação Simples, que consiste no sorteio aleatório de duas posições (dois genes) no indivíduo, havendo a troca do conteúdo entre estas duas posições. A permutação simples é ilustrada na Figura 4.11. Essa mutação pode provocar indivíduos que não respeitem as precedências.

Fig. 4.10: Exemplo de crossover cíclico [89].

Fig. 4.11: Exemplo de permutação simples [89].

Foi utilizado como critério de término, o número máximo de 300 gerações. A taxa de indiví- duos selecionados para o processo de crossover foi igual a 60%. A população foi formada por 250 indivíduos e a taxa de mutação por indivíduo foi de 40%.

O tempo total de execução T mínimo para o Gauss18 utilizando-se dois processadores é igual a 44 unidades de tempo. Existem diferentes soluções para este problema com T = 44,0. A abordagem descrita convergiu 7 vezes para uma solução ótima, em 10 execuções do AG. A Figura 4.12 apresenta dois exemplos de indivíduos obtidos, que retornam T = 44,0.

Fig. 4.12: Soluções ótimas obtidas com o AG no escalonamento do Gauss18 [89].

4.3.2 Algoritmo Branch-and-Bound aplicado ao escalonamento de tarefas em

multiprocessadores

Os algoritmos branch-and-bound (B&B) são muito usados para resolver problemas combinatoriais. Estes algoritmos são baseados na idéia de enumerar todas as soluções praticáveis de um problema de forma direcionada e inteligente [16]. Uma solução é praticável se ela é uma solução completa “aceitável” para um determinado problema [55].

O B&B tem sido utilizado para encontrar soluções ótimas (ou sub-ótimas) para o problema do es- calonamento de tarefas em sistemas multiprocessadores [82]. Ele é um eficiente algoritmo de busca no espaço de soluções para o problema de escalonamento. Este espaço de soluções é frequentemente representado por uma estrutura de árvore, onde cada vértice da árvore representa uma solução com- pleta ou parcial para o problema. Utilizando-se de regras inteligentes para a seleção de vértices a explorar/expandir (branch) e também para a exclusão de vértices (bound) que não conduzam a uma solução ótima, a complexidade da busca pode ser reduzida quando comparada a métodos de busca enumerativa exaustiva. Ou seja, a escolha das regras de branch e bound são fundamentais para o sucesso do algoritmo.

Diante do fato da complexidade exponencial do algoritmo B&B não poder ser eliminada, a sua aplicabilidade, em geral, restringe-se a pequenos sistemas. Mas, quando as características da apli- cação e/ou a arquitetura de processamento são conhecidas e podem ser exploradas eficientemente, o B&B pode ser bem aplicado mesmo para grandes sistemas [2, 52].

No método B&B, a busca por uma solução para o escalonamento multiprocessador é feita em uma árvore de busca que representa o espaço de soluções do problema, que são todas as possíveis permutações de atribuição tarefa-para-processador e ordem de execução das tarefas, isto é, a ordem de escalonamento. Cada vértice na árvore representa uma atribuição tarefa-para-processador, uma ordem

composto por 4 tarefas e a Figura 4.13b apresenta um exemplo de árvore de busca para este grafo.

Fig. 4.13: Exemplo de árvore de busca: (a) grafo de precedência de tarefas e (b) árvore de busca.

Um vértice objetivo na árvore de busca representa uma solução completa onde todas as tarefas foram alocadas nos processadores. O nível de um vértice é o número de tarefas que foram atribuídas para qualquer processador no escalonamento (nó da árvore) corrente. O custo de um vértice é a

qualidade do escalonamento representado pelo vértice. Em [55], o custo é o atraso máximo de tarefa para o escalonamento representado pelo vértice.

Quando não há restrições de precedência entre as tarefas, considerando n tarefas e m processa- dores, o número de vértices objetivo na árvore de busca é n!mn. Se as restrições de precedência são consideradas, o número de vértices objetivo na árvore de busca é reduzido para quase knmn, sendo

ko número máximo de vértices filhos de um vértice. Devido ao crescimento exponencial do número de vértices na árvore de busca, vértices não são, normalmente, gerados até que o algoritmo B&B ne- cessite explorá-los. Quando um novo vértice é gerado e ele pode levar a uma solução solução ótima, ele é chamado de vértice ativo. Geralmente, uma heurística é utilizada para definir a ordem em que os vértices serão explorados na árvore de busca. A estratégia B&B consiste em alternar operações de

branchinge bounding no conjunto de vértice ativos. Branching (ramificando) é o processo de gerar vértices filhos de um vértice ativo, e bounding (avaliando) é o processo de avaliar o custo de novos vértices filhos, para posteriormente decidir se eles também serão ramificados.

A Figura 4.14 apresenta o algoritmo branch-and-bound apresentado em [55] para a solução do escalonamento de tarefas em multiprocessadores. O algoritmo recebe um grafo de programa como entrada e produz um grafo de tarefas “anotado”, contendo informações sobre os tempos de início e término das tarefas para o melhor escalonamento. Neste algoritmo, um conjunto ativo AS é utilizado para armazenar todos os vértices ativos.

Neste capítulo apresentamos a arquitetura do escalonador de tarefas em multiprocessadores baseado em ACs proposto em [94], os modelos de vizinhança de AC propostos na literatura [94, 102] e uti- lizados neste trabalho, e experimentos que reproduzimos (simulamos) a partir de publicações dos principais pesquisadores nesta área.

Este capítulo está organizado da seguinte maneira. Na Seção 5.1 são apresentados os principais conceitos, os modelos de vizinhança e a arquitetura de um escalonador de tarefas em multiprocessado- res basedo em autômatos celulares (ACs), proposto originalmente em [94]. Na Seção 5.2 discutimos a capacidade de generalização das regras de transição de ACs, que é fundamental para o escalonador baseado em ACs. Na Seção 5.3 apresentamos os principais grafos de programa utilizados nos expe- rimentos realizados. Na Seção 5.4 são apresentadas as configurações utilizadas para a realização dos experimentos. Na Seção 5.5 são apresentados resultados experimentais obtidos com a utilização do modelo de vizinhança linear de AC. Na Seção 5.6 são apresentados resultados experimentais obtidos com a utilização dos modelos de vizinhança não-lineares e com o modo de operação (atualização) de ACs seqüencial (Seção 3.2.2). Os resultados experimentais apresentados nas Seções 5.5 e 5.6 incluem alguns experimentos que simulamos, a partir de resultados originais, isto é, trabalhos relaci- onados publicados, buscando reproduzir e aprofundar esses resultados, além de alguns experimentos que realizamos para avaliar a capacidade de generalização das regras descobertas.

Nos experimentos descritos nesse capítulo, utilizamos a mesma abordagem proposta em [94], que chamamos de Evolução Simples. No próximo capítulo, descreveremos experimentos que realizamos

Celulares 70 em algumas modificações da arquitetura do escalonador, que propomos nessa dissertação. Essas modificações se referem à fase de aprendizagem, onde a busca genética sofreu alterações com o objetivo de melhorar a capacidade de generalização das regras evoluídas.

5.1 Escalonamento de Tarefas em Multiprocessadores baseado

em Regras de Autômatos Celulares

Nesta seção, são apresentados os principais conceitos e a arquitetura de um escalonador de tarefas em multiprocessadores baseado em autômatos celulares (ACs). Essa arquitetura foi proposta inicialmente em [94]. São apresentados três modelos diferentes para a formação da vizinhança do AC utilizado para o escalonamento: uma vizinhança linear [102], baseada no raio r do AC, e duas vizinhanças não-lineares [96], associadas a uma tarefa k do grafo de programa, baseadas nos conjuntos de tarefas

predecessoras(k), irmãs(k) e sucessoras(k).