Suspender / hibernar automaticamente um processo quando muita memória é tirada

6

Estou executando um pequeno cluster de computação Debian em PCs de 8 núcleos com 16 GB de RAM. Estou executando lotes de cerca de 1k tarefas (cada lote tem um tempo total esperado de um mês para ser concluído). Uma única tarefa é single-threaded (para que eu possa executar vários deles em paralelo em cada PC), não consome muito IO (carrega vários megabytes de dados no início e despeja vários megabytes de dados na saída; não se comunica com o mundo externo caso contrário), seu tempo de execução é desconhecido (de poucos minutos a ~ semana), seu consumo de memória é desconhecido (variando de vários megabytes a ~ 8 GB; o uso pode crescer lenta ou rapidamente). Gostaria de fazer o maior número possível de tarefas paralelas em um único PC, mas quero evitar uma troca excessiva.

Então eu tive uma idéia: eu poderia monitorar o uso de memória dessas tarefas e suspender ( kill -SIGSTOP ) ou hibernar (usando uma ferramenta como CryoPID ) tarefas que consomem muita memória para reiniciá-las mais tarde. Por uso de memória, quero dizer o número de “páginas virtuais ativas” ou o número de páginas de memória compartilhada que não foram alocadas (essas tarefas podem alocar memória sem usá-las).

Eu comecei a procurar algumas ferramentas para fazer isso. Eu sei que posso ulimit ou executar uma tarefa dentro de um cgroup limitado por memória, mas - se eu os entendi corretamente - essas soluções irão matar o processo em vez de suspendê-lo. Eu quero evitar matá-los, porque eu precisaria iniciá-los do zero mais tarde, e isso significa perda de tempo. Além disso, eles não podem medir o número de páginas virtuais ativas.

Eu poderia usar máquinas virtuais reais, mas elas parecem ter uma sobrecarga significativa neste caso - ter kernel separado, alocações de memória, etc. diminuiria a memória disponível; Eu teria que correr 8 deles. Além disso, até onde sei, eles também acrescentariam sobrecarga computacional.

Eu imagino que uma ferramenta que implementaria tal comportamento conectaria alguma função a uma notificação de falha de página que decidiria sobre cada falha de página se é hora de suspender o processo ou não. Mas eu não conheço nenhuma ferramenta que funcione dessa maneira também.

Existem outras opções?

    
por liori 10.06.2013 / 03:44

2 respostas

2

O que você está se referindo é o processo de verificação. Há algum trabalho nos kernels posteriores para oferecer isso (em conjunto com o freezer cgroup), mas ainda não está pronto.

Na verdade, isso é muito difícil de ser alcançado porque certos recursos compartilhados ficam obsoletos depois de ficarem indisponíveis por um período fixo de tempo (TCP vem à mente, embora isso também possa se aplicar a aplicativos que usam um relógio de parede ou talvez alguma memória compartilhada que muda de estado durante um período de processos off-line).

Quanto a interromper o processo quando ele alcança uma certa utilização de memória, existe um hack que eu posso pensar que vai fazer isso.

  • Você cria um cgroup que contém os subsistemas freezer e memory.
  • Coloque sua (s) tarefa (s) dentro do cgroup.
  • Anexe um processo a cgroup.event_control e defina um limite de memória que você não deseja exceder (isso é explicado de alguma forma no documentação do kernel .
  • Ao exceder o tempo, você congela o cgroup. O kernel deve eventualmente despejar essas páginas para trocar (desde que seu cgroup tenha o suficiente).

Observe que o cgroup "freeze" não despejará páginas em um local persistente de mídia, mas trocará as páginas quando houver tempo suficiente e as páginas forem necessárias para outra coisa.

Mesmo que isso funcione (é bastante hacky se isso acontecer), é necessário considerar se isso realmente está ou não fazendo alguma coisa para resolver seu problema.

  • Como você sabe que não seria melhor permitir que um processo usando muita memória fosse mais rápido para concluir rapidamente seu período intensivo de memória e abrir mão da memória?
  • Se você tentar despertar os processos de forma justa pelos processos de round-robining, poderá argumentar que está fazendo um trabalho pior do que o que o planejador de CPU já está fazendo por você.
  • Se alguns processos são mais importantes do que outros (e devem ser acordados por mais tempo), provavelmente é melhor alocá-los mais tempo de CPU do que manter outros processos completamente congelados.
  • Embora seja lento - você pode adicionar muito swap (para que você nunca possa supercomprometer) e reduzir bastante a interatividade do agendador para tentar ajudar a reduzir despejos agressivos de páginas. Isso é feito em sched_min_granularity_ns .

Infelizmente, a melhor solução seria a capacidade de verificar suas tarefas. É uma pena que a maioria das implementações não seja tão concreta assim ainda.

Como alternativa, você pode esperar alguns anos para que o ponto de verificação / restauração esteja disponível no kernel!

    
por 11.06.2013 / 01:23
0

Eu estou supondo que esta pergunta está um pouco acima da minha cabeça, ou eu entendi errado, mas você está procurando algo como

ps auxww e depois verificando a coluna VSZ. Então, se VSZ atinge uma certa quantia, você executa seu SIG nesse processo? E então apenas execute o comando no seu intervalo favorito?

Da página de manual do ps

vsz VSZ tamanho da memória virtual do processo em KiB (unidades de 1024 bytes). Os mapeamentos de dispositivos estão atualmente                     excluído; Isto está sujeito a alterações. (alias vsize).

    
por 11.06.2013 / 00:39