Condor é um projeto desenvolvido pela universidade Wisconsin-Madison, que objetiva criar um ambiente capaz de prover grande poder computacional a médio e longo prazo. Para isso, utiliza-se de recursos computacionais ociosos de equipamentos não dedicados. Entretanto, nada impede a utilização desse sistema em Clusters dedicados. Essa modalidade de processamento é chamada de Computação de Alta Vazão (High-Thoughput Computing ou HTC). Em muitos projetos de pesquisa ou de engenharia é comum a necessidade de execução de programas (por exemplo, em simulações) que necessitem de semanas ou meses de execução para serem resolvidos. É justamente essa a classe de aplicações que o Condor objetiva suportar.
O funcionamento do Condor baseia-se na execução de jobs. O usuário submete um Job ao sistema. Condor, por sua vez, encontra os recursos disponíveis para a execução. O sistema Condor monitora continuamente a execução dos jobs. Quando uma máquina executando um job torna-se indisponível (por exemplo, pelo retorno do usuário), Condor pode realizar um Checkpoint do job e migrá-lo para uma outra máquina que esteja disponível. Dessa forma, a execução na outra máquina poderá prosseguir do ponto em que havia parado.
O usuário Condor tem a ilusão de que as tarefas remotas são executadas localmente. De forma a tornar possível o acesso à maior quantidade possível de máquinas, Condor não assume que as máquinas para a execução remota montam os mesmos sistemas de arquivos da máquina do usuário. Para solucionar esta questão, Condor realiza o redirecionamento das chamadas de sistema da máquina que está executando o job para a máquina base do usuário. Condor provê uma biblioteca de redirecionamento para esta função.
Para a organização e especialização foram definidas algumas funções que uma determinada máquina poderá possuir. Abaixo são descritas as funções Condor existentes:
Para instalar o Condor, inicialmente deve-se efetuar o download de versões pré-compiladas do software, a partir do site http://www.cs.wisc.edu/condor/. Por decisão dos responsáveis, os fontes dessa ferramenta não são fornecidos liberadamente. Para ter acesso aos mesmos, deve-se enviar um e-mail justificando a necessidade.
É recomendável que a instalação seja executada por um usuário com direitos administrativos no equipamento em questão. Abaixo segue descrito o procedimento detalhado de instalação do Condor:
# tar xvfz condor-6.6.10-linux-x86-redhat80-dynamic.tar.gz
condor_configure [--install] [--type =] [--central-manager = < hostname>] [--owner = ] [--verbose]
Abaixo temos a descrição dos parâmetros do comando condor_configure:
| --install | Especifica que uma nova instalação está sendo realizada |
| --type | Define a configuração Condor estará sendo realizada, baseando-se nos papéis possíveis (seção 2) |
| --central-manager | Especifica o central-manager a ser utilizado |
| --owner | Define o usuário utilizado para iniciar os daemons do Condor |
| --verbose | mostra os detalhes da instalação a ser realizada |
Para ilustrar este procedimento, segue abaixo os comandos para a instalação em uma máquina que conterá todas as funções possíveis.
# cd condor-6.6.10 # condor_configure --install --install-dir=/Programs/condor --type=submit,execute,manager --verbose --central-manager=127.0.0.1 --owner=condor
Os passos acima ilustram a instalação recomendada para o Condor, no qual os parâmetros necessários são passados no início do processo. Existe, porém, um método alternativo de instalação baseado na entrada de dados do usuário para cada informação necessária. Este segundo método baseia-se no script Perl condor_install e deve ser usado quando a instalação automática não for possível. Abaixo esta opção de instalação é mostrada.
# perl condor_install
Conforme já comentado, as máquinas em um sistema Condor poderão possuir funções específicas relativas ao seu papel (Central-Manager, Execute ou Submit). Para cada função, entretanto, um determinado conjunto de daemons deve ser iniciado. Tais funções são definidas no momento da instalação. Dessa forma, os daemons que deverão ser iniciados no equipamento são definidos no arquivo
Iniciar os daemons necessários é uma tarefa bastante simples, na medida que este gerenciamento é feito pelo próprio middleware. Basta que o usuário inicie o processo condor_master, que se encarregará de iniciar os daemons necessários ao ambiente em questão. Abaixo este procedimento é mostrado:
$ condor_master
Inicialmente, é importante entender como o Condor realiza a alocação dos recursos para os jobs. O Matchmaker é o componente responsável por esta tarefa. Outro conceito importante é o Condor Pool, que refere-se ao ambiente de execução dentro de um mesmo domínio administrativo.
Assim, todas as máquinas em um pool publicam os seus atributos, sejam eles estáticos ou dinâmicos, tais como memória RAM, tipo e velocidade da CPU, etc. No momento em que um job for submetido, o Matchmaker analisa os seus atributos e aloca as máquinas disponíveis que se adequarem a tais requisitos. Ou seja, ele confronta os atributos dos jobs com a informação publicada das máquinas de forma a realizar as alocações possíveis. É importante mencionar que junto aos atributos das máquinas também estão disponíveis as suas políticas de utilização. Por exemplo, o proprietário de um recurso pode especificar que ele poderá ser utilizado somente após às 20h00.
Inicialmente, é importante entender os status possíveis de job que uma determinada máquina de execução poderá possuir em determinado momento. A tabela abaixo descreve os status existentes:
| Status | Descrição |
| Idle | Máquina livre sem execução do job |
| Busy | Job em execução |
| Suspended | Job neste momento sendo suspenso |
| Vacating | Job está atualmente sendo checkpointed |
| Killing | Job está neste momento sendo finalizado |
| Benchmarking | A máquina está atualmente executando bechmarks, ou seja, gerando estatísticas sobre a execução de um job |
Para a correta execução de jobs no Condor é necessário que alguns passos sejam seguidos. Tais passos seguem abaixo descritos:
$ condor_compile cc main.o tools.o -o program
Considerando o roadmap de execução informado acima, a submissão de jobs é um passo que merece ser explanado mais detalhadamente. Resumidamente, o comando abaixo realiza a submissão de um job chamado prog1 para a execução em Condor Pool:
$ condor_submit prog1
No arquivo de descrição de job, deve ser informado ao Condor os detalhes necessários à execução do job. Tais arquivos possuem uma sintaxe pré-definida, que será descrita através de exemplos, nas próximas subseções.
Este exemplo ilustra a forma simples de se submeter um job ao Condor. Ele envia à fila de execução Condor uma cópia do programa foo, que foi criado com o compilador condor_compile. Um arquivo de log (foo.log) será gerado e irá conter os eventos de execução do job. Quando o job finalizar, o status de saída também será gravado no arquivo foo.log.
################################################
# Exemplo simples de utilização do Condor
################################################
Executable = foo
Log = foo.log
Queue
Neste exemplo, teremos a execução de duas cópias do programa mathematica. A primeira cópia será executada no diretório run_1 e a segunda, no diretório run_2. Para as duas execuções o arquivo test.data será utilizado como entrada. Será criado o arquivo loop.out com os dados de saída. Teremos o arquivo loop.err com o redirecionamento de stderr. Interessante ressaltar o uso da cláusula Universe, no qual foi definida a utilização do universo Vanilla.
##################################################
# Exemplo de utilização de múltiplos diretórios
##################################################
Executable = mathematica
Universe = vanilla
input = test.data
output = loop.out
error = loop.error
Log = loop.log
Initialdir = run_1
Queue
Initialdir = run_2
Queue
Nesta seção será exemplificada uma situação de uso mais realística. O arquivo em questão enfileira 150 execuções do programa foo, que foi compilado para plataforma Silicon Graphics, executando sistema operacional IRIX 6.5. O job deverá ser executado em máquinas que possuam mais de 256 Mb de memória RAM. A cláusula RANK nos informa, entretanto, que a preferência de execução será dada às máquinas que possuírem mais de 512 Mb de memória RAM.
Image_Size informa ao sistema Condor a quantidade de memória a ser alocada na execução do job. Isso possibilita que o Condor aloque para a execução máquinas que possuam mais de 64 Mb de memória livre. A cláusula Queue nos informa que serão submetidas 150 execuções deste job ao sistema. A variável $(Process) identifica o número do job, ou seja, como resultado da primeira execução será gerado um arquivo de saída chamado de in.0, como resultado da segunda, in.2, e assim por diante.
##################################################### # Utilização de restrições para a execução dos jobs ##################################################### Executable = foo Requirements = Memory >= 256 && OpSys == "IRIX65" && Arch =="SGI" Rank = Memory >= 512 Image_Size = 64 Meg Error = err.$(Process) Input = in.$(Process) Output = out.$(Process) Log = foo.log Queue 150
Condor estabelece duas classes independentes de prioridade: prioridade de job e prioridade de usuário. Para controlar a execução, a cada job é atribuída uma determinada prioridade. Para alterar a prioridade padrão dos jobs deve ser utilizado o comando condor_prio. Prioridades de job, entretanto, não afetam as prioridades de usuário. As prioriridades de job são distribuídas no intervalo de -20 a +20, sendo -20 o pior caso e, conseqüentemente, +20 o melhor.
Máquinas são alocadas aos usuários, considerando as suas prioridades. Quanto menor o valor numérico, maior será a prioridade na alocação de máquinas. Por exemplo, um usuário com prioridade 10 irá receber duas vezes mais recursos que um usuário com prioridade 20. As prioridades de usuário podem ser visualizadas com comando condor_userprio. A prioridade do usuário vai alterando-se de acordo com o número de recursos por ele alocados. Assim, todo o usuário inicia com prioridade 0,5.
Em outras palavras a prioridade do usuário indica o número de máquinas por ele alocadas. O sistema condor, assim, beneficia o usuário com o menor número de máquinas de forma a garantir a justiça no acesso aos recursos.
Se o número de máquinas que o usuário atualmente possui é maior que a sua prioridade, o valor numérico de sua prioridade aumenta de forma adequar-se a este valor. Se o número de máquinas é menor que o valor numérico de sua prioridade, o valor é proporcionalmente reduzido. Este método objetiva obter justiça no acesso aos recursos para todos os usuários. Por exemplo, se um usuário de baixa prioridade está utilizando todas as máquinas disponíveis e um novo usuário realiza a submissão de seus jobs, Condor imediatamente realiza o checkpoint dos jobs do primeiro usuário e os suspende para posterior retorno, migrando-o ou não para outro equipamento. Por padrão, o Condor só irá preemptar os jobs de usuário que tiverem sido iniciados em até 1 hora. Entretanto, este critério poderá ser alterado nos arquivos de configuração do Condor. É importante ressaltar também que o Administrador Condor poderá elevar ou reduzir a prioridade de determinado usuário diretamente.
Muitas vezes encontramos situações onde jobs possuem como dependência para a sua execução o término de outros. Com o intuito de prover uma alternativa a esta necessidade o Condor oferece o utilitário DagMan que gerencia a execução de jobs através de um grafo acíclico direcionado (directed acyclick graph – DAG). Os jobs são os vértices no grafo e as arestas identificam as suas dependências.
Os mecanismos do Condor não são capazes de considerar as dependências entre os jobs. Assim, o DAGMan realiza a função de um meta-escalonador. DAGMan submete os jobs para o Condor, de forma necessária a satisfazer as suas dependências.
Para realizar o escalonamento adequado, DAGMan monitora os logs do Condor para assegurar o ordenamento requerido para a execução dos Jobs. Para a sua operação um arquivo texto em um formato pré-definido deverá ser submetido. Abaixo verificamos um exemplo de um arquivo no formato do DAGMan, informando a dependência entre os jobs.
# Arquivo: diamond.dag # Área 1 Job A A.condor Job B B.condor Job C C.condor Job D D.condor # Área 2 Script PRE A top_pre.csh Script PRE B mid_pre.perl $JOB Script POST B mid_post.perl $JOB $RETURN Script PRE C mid_pre.perl $JOB Script POST C mid_post.perl $JOB $RETURN Script PRE D bot_pre.csh # Área 3 PARENT A CHILD B C PARENT B C CHILD D # Área 4 Retry C 3
Ao analisar o arquivo diamond.dag verificamos a existência de quatro áreas distintas. A primeira define os jobs a serem executados e o arquivo que contém a sua definição. Por exemplo, na primeira linha verificamos o Job A que têm a sua definição no arquivo A.condor.
A segunda área do arquivo define os scripts a serem executados antes (PRE) ou após (POST) a execução dos jobs. No caso, teremos o script top_pre.csh sendo executado antes do job A.
Na área 3 temos a definição das dependências entre os jobs. A figura abaixo ilustra as dependências entre os jobs supracitados.
Na área 4, temos a opção de definir que, caso um job tenha finalizado com falha, o mesmo poderá ser reiniciado N vezes. No exemplo, temos o job C que poderá ser reiniciado até 3 vezes em caso de falhas.