13. Execução de cache e de reentrância¶
O mecanismo de caching do Nextflow funciona atribuindo uma ID única para cada tarefa que é usada para criar um diretório de execução separado onde as tarefas são executadas e os resultados guardados.
A ID única de tarefa é gerada como uma hash de 128-bit compondo os valores de entrada da tarefa, arquivos e a string de comando.
O diretório de trabalho do fluxo de trabalho é organizado como mostrado abaixo:
work/
├── 12
│ └── 1adacb582d2198cd32db0e6f808bce
│ ├── genome.fa -> /data/../genome.fa
│ └── index
│ ├── hash.bin
│ ├── header.json
│ ├── indexing.log
│ ├── quasi_index.log
│ ├── refInfo.json
│ ├── rsd.bin
│ ├── sa.bin
│ ├── txpInfo.bin
│ └── versionInfo.json
├── 19
│ └── 663679d1d87bfeafacf30c1deaf81b
│ ├── ggal_gut
│ │ ├── aux_info
│ │ │ ├── ambig_info.tsv
│ │ │ ├── expected_bias.gz
│ │ │ ├── fld.gz
│ │ │ ├── meta_info.json
│ │ │ ├── observed_bias.gz
│ │ │ └── observed_bias_3p.gz
│ │ ├── cmd_info.json
│ │ ├── libParams
│ │ │ └── flenDist.txt
│ │ ├── lib_format_counts.json
│ │ ├── logs
│ │ │ └── salmon_quant.log
│ │ └── quant.sf
│ ├── ggal_gut_1.fq -> /data/../ggal_gut_1.fq
│ ├── ggal_gut_2.fq -> /data/../ggal_gut_2.fq
│ └── index -> /data/../asciidocs/day2/work/12/1adacb582d2198cd32db0e6f808bce/index
Info
Você pode criar esse plot usando a função tree
se você a tiver instalada. No unix, simplesmente use sudo apt install -y tree
ou com Homebrew: brew install tree
13.1 Como funciona a reentrância¶
A opção de linha de comando -resume
permite a continuação da execução do fluxo de trabalho pelo último passo que foi completado com sucesso:
Em termos práticos, o fluxo de trabalho é executado do início. Entretanto, antes do lançamento da execução de um processo, o Nextflow usa a ID única da tarefa para checar se o diretório de trabalho existe e se ele contém um estado de saída válido do comando com os esperados arquivos de saída.
Se esta condição for satisfeita a tarefa é ignorada e os resultados computados previamente são usados como resultados do processo.
A primeira tarefa que tem uma nova saída computada invalida todas execuções posteriores no que resta do Grafo Acíclico Direcionado (DAG, do inglês Directed Acyclic Graph).
13.2 Diretório de trabalho¶
O diretório de trabalho das tarefas é criado por padrão na pasta work
no mesmo diretório onde o fluxo de trabalho foi executado. Essa localização é supostamente uma área de armazenamento provisória que pode ser limpada quando a execução do fluxo de trabalho for finalizado.
Note
As saídas finais do fluxo de trabalho geralmente são guardadas em uma localização diferente especificada usando uma ou mais diretivas publishDir.
Warning
Certifique-se de deletar o diretório de trabalho ocasionalmente, se não sua máquina ou ambiente estará cheia de arquivos sem uso.
Uma localização diferente para o diretório de trabalho pode ser especificada usando a opção -w
. Por exemplo:
Warning
Se você deletar ou mover o diretório de trabalho do fluxo de trabalho, isso irá impedir que você use o recurso de reentrância nas execuções posteriores.
O código hash para os arquivos de entrada são computados usando:
- O caminho completo do arquivo
- O tamanho do arquivo
- A última marcação de tempo de modificação
Portanto, o simples uso do touch em um arquivo irá invalidar a execução da tarefa relacionada.
13.3 Como organizar experimentos in-silico¶
É uma boa prática organizar cada experimento em sua própria pasta. Os parâmetros de entrada do experimento principal devem ser especificados usando o arquivo de configuração do Nextflow. Isso torna simples acompanhar e replicar o experimento ao longo do tempo.
Note
No mesmo experimento, o mesmo fluxo de trabalho pode ser executado diversas vezes, entretanto, iniciar duas (ou mais) instâncias do Nextflow no mesmo diretório ao mesmo tempo deve ser evitado.
O comando nextflow log
lista todas as execuções na pasta atual:
$ nextflow log
TIMESTAMP DURATION RUN NAME STATUS REVISION ID SESSION ID COMMAND
2019-05-06 12:07:32 1.2s focused_carson ERR a9012339ce 7363b3f0-09ac-495b-a947-28cf430d0b85 nextflow run hello
2019-05-06 12:08:33 21.1s mighty_boyd OK a9012339ce 7363b3f0-09ac-495b-a947-28cf430d0b85 nextflow run rnaseq-nf -with-docker
2019-05-06 12:31:15 1.2s insane_celsius ERR b9aefc67b4 4dc656d2-c410-44c8-bc32-7dd0ea87bebf nextflow run rnaseq-nf
2019-05-06 12:31:24 17s stupefied_euclid OK b9aefc67b4 4dc656d2-c410-44c8-bc32-7dd0ea87bebf nextflow run rnaseq-nf -resume -with-docker
Você pode usar tanto o ID da sessão ou o nome da execução para recuperar uma execução específica. Por exemplo:
13.4 Proveniência da execução¶
O comando log
, quando provido do nome da execução ou ID da sessão, pode retornar algumas informações importantes sobre um fluxo de trabalho em execução que podem ser usadas para criar um relatório de proveniência.
Por padrão, o comando irá listar todos diretórios de trabalho usados em cada tarefa. Por exemplo:
$ nextflow log tiny_fermat
/data/.../work/7b/3753ff13b1fa5348d2d9b6f512153a
/data/.../work/c1/56a36d8f498c99ac6cba31e85b3e0c
/data/.../work/f7/659c65ef60582d9713252bcfbcc310
/data/.../work/82/ba67e3175bd9e6479d4310e5a92f99
/data/.../work/e5/2816b9d4e7b402bfdd6597c2c2403d
/data/.../work/3b/3485d00b0115f89e4c202eacf82eba
A opção -f
(do inglês, fields) pode ser usada para especificar qual metadado deve ser impresso pelo comando log
. Por exemplo:
$ nextflow log tiny_fermat -f 'process,exit,hash,duration'
index 0 7b/3753ff 2.0s
fastqc 0 c1/56a36d 9.3s
fastqc 0 f7/659c65 9.1s
quant 0 82/ba67e3 2.7s
quant 0 e5/2816b9 3.2s
multiqc 0 3b/3485d0 6.3s
A lista completa dos campos disponíveis pode ser recuperada com o comando:
A opção -F
permite a especificação de um critério de filtro para imprimir apenas um subconjunto de tarefas. Por exemplo:
$ nextflow log tiny_fermat -F 'process =~ /fastqc/'
/data/.../work/c1/56a36d8f498c99ac6cba31e85b3e0c
/data/.../work/f7/659c65ef60582d9713252bcfbcc310
Isso pode ser útil para localizar um diretório de trabalho de uma tarefa específica.
Finalmente, a opção -t
permite a criação de um relatório básico e customizável de proveniência, mostrando um modelo de arquivo em qualquer formato de sua escolha. Por exemplo:
<div>
<h2>${name}</h2>
<div>
Script:
<pre>${script}</pre>
</div>
<ul>
<li>Exit: ${exit}</li>
<li>Status: ${status}</li>
<li>Work dir: ${workdir}</li>
<li>Contêiner: ${container}</li>
</ul>
</div>
Exercise
Salve o trecho acima em um arquivo chamado template.html
. Então execute o comando (usando o ID correto para sua execução, ex. tiny_fermat
):
Finalmente, abra o arquivo prov.html
com um navegador.
13.5 Resolução de problemas de reentrância¶
Ser capaz de retomar fluxos de trabalho é um recurso importante do Nextflow, mas nem sempre funciona como você espera. Nesta seção, analisamos alguns motivos comuns pelos quais o Nextflow pode estar ignorando seus resultados em cache.
Tip
Para saber mais detalhes sobre o mecanismo de reentrância e como solucionar problemas, consulte as três postagens de blog a seguir:
13.5.0.1 Arquivos de entrada mudados¶
Tenha certeza que não há nenhuma mudança no(s) arquivo(s) de entrada. Não esqueça que cada tarefa tem seu hash único que é computado levando em conta o caminho completo do arquivo, a última marcação de tempo de modificação e o tamanho do arquivo. Se alguma dessas informações foi alterada, o fluxo de trabalho deve ser re-executado mesmo que o conteúdo do arquivo seja o mesmo.
13.5.0.2 Um processo modifica uma entrada¶
Um processo nunca deve alterar os arquivos de entrada, se não a função resume
em execuções futuras será invalidada pela mesma razão explicada no ponto anterior.
13.5.0.3 Atributos de arquivos inconsistentes¶
Alguns sistemas de arquivos compartilhados, como o NFS, podem reportar uma marcação de tempo inconsistente para os arquivos (por exemplo, uma diferente marcação de tempo para um mesmo arquivo) até mesmo quando este não foi modificado. Para prevenir esse problema use a estratégia de cache leniente.
13.5.0.4 Condição de corrida em uma variável global¶
O Nextflow é desenvolvido para simplificar programação paralela, de modo que você não precise se preocupar com condições de corrida e acesso a recursos compartilhados. Um dos poucos casos que uma condição de corrida pode surgir é quando uma variável global é utilizada com dois (ou mais) operadores. Por exemplo:
O problema desse trecho é que a variável X
na clausura é definida no escopo global. Portanto, como operadores são executados em paralelo, o valor de X
pode ser sobrescrito pela outra invocação do map
.
A implementação correta requer o uso da palavra chave def
para declarar a variável local.
13.5.0.5 Canais de entrada não determinísticos.¶
Embora a ordem de elementos em canais dataflow seja garantida – os dados são lidos na mesma ordem em que são escritos no canal – saiba que não há garantia de que os elementos manterão sua ordem no canal de saída do processo. Isso ocorre porque um processo pode gerar várias tarefas, que podem ser executadas em paralelo. Por exemplo, a operação no segundo elemento pode terminar antes da operação no primeiro elemento, alterando a ordem dos elementos no canal de saída.
Em termos práticos, considere o trecho a seguir:
Assim como vimos no início deste tutorial com HELLO WORLD ou WORLD HELLO, a saída do trecho acima pode ser:
..e essa ordem provavelmente será diferente toda vez que o fluxo de trabalho for executado.
Imagine agora que temos dois processos como este, cujos canais de saída estão atuando como canais de entrada para um terceiro processo. Ambos os canais serão aleatórios de forma independente, portanto, o terceiro processo não deve esperar que eles retenham uma sequência pareada. Se assumir que o primeiro elemento no primeiro canal de saída do processo está relacionado ao primeiro elemento no segundo canal de saída do processo, haverá uma incompatibilidade.
Uma solução comum para isso é usar o que é comumente chamado de meta mapa (meta map). Um objeto groovy com informações de amostra é distribuído junto com os resultados do arquivo em um canal de saída como uma tupla. Isso pode então ser usado para emparelhar amostras que estão em canais separados para uso em processos posteriores. Por exemplo, em vez de colocar apenas /algum/caminho/minhasaida.bam
em um canal, você pode usar ['SRR123', '/algum/caminho/minhasaida.bam']
para garantir que os processos não incorram em uma incompatibilidade. Verifique o exemplo abaixo:
Se os meta mapas não forem possíveis, uma alternativa é usar a diretiva de processo fair
. Quando especificada, o Nextflow garantirá que a ordem dos elementos nos canais de saída corresponderá à ordem dos respectivos elementos nos canais de entrada. É importante deixar claro que a ordem em que as tarefas serão concluídas não será necessariamente a ordem dos elementos no canal entrada, mas Nextflow garante que, ao final do processamento, os elementos no canal de saída estarão na ordem correta.
Warning
Dependendo da sua situação, usar a diretiva fair
levará a uma queda de desempenho.