¿Qué hace si tiene muchos trabajos informáticos para ejecutar y muchos recursos informáticos para ejecutarlos?
¡Juguemos con algunas opciones! Ejecutaremos un conjunto simple de análisis bioinformáticos como ejemplo, pero todos los enfoques a continuación deberían funcionar para una amplia variedad de necesidades de línea de comando.
La mayoría de los comandos a continuación deberían funcionar como copiar/pegar directamente. Por favor, hágamelo saber si no lo hacen!
Configuración y preparación de archivos.
Descargue algunos ensamblajes de metagenomas de nuestro proyecto de evaluación del ensamblaje del metagenoma. Estos son todos los archivos generados a partir de Shakya et al., 2014 – en concreto, montajes de SRR606249.
mkdir queries/
cd queries/
curl -JLO https://osf.io/download/q8h97/
curl -JLO https://osf.io/download/7bzrc/
curl -JLO https://osf.io/download/3kgvd/
cd ..
mkdir -p database/
cd database/
curl -JLO https://osf.io/download/4kfv9/
cd ../
Ahora deberías tener tres archivos en queries/
>idba.scaffold.fa.gz
>megahit.final.contigs.fa.gz
>spades.scaffolds.fasta.gz
y un archivo en la base de datos/
>podar-complete-genomes-17.2.2018.tar.gz
Bosquejemos las consultas con sourmash:
for i in queries/*.gz
do
sourmash sketch dna -p k=31,scaled=10000 $i -o $i.sig
done
A continuación, descomprima la base de datos y cree database.zip
:
cd database/
tar xzf podar*.tar.gz
sourmash sketch dna -p k=31,scaled=10000 *.fa --name-from-first -o ../database.zip
cd ../
Finalmente, haga que todas sus entradas sean de solo lectura:
chmod a-w queries/* database.zip database/*
Esto evita que se sobrescriban accidentalmente los archivos.
Ejecutando sus consultas básicas
vamos a correr reunión de puré de agria para los tres archivos de ensamblaje en queries/
contra los 64 genomas en database.zip
. Estos comandos específicos se ejecutarán rápidamente, pero tenga en cuenta que son un proxy para un análisis mucho más grande en bases de datos más grandes.
Podrías hacer estas consultas en serie:
sourmash gather queries/idba.scaffold.fa.gz.sig
database.zip -o idba.scaffold.fa.gz.csv
sourmash gather queries/megahit.final.contigs.fa.gz.sig
database.zip -o megahit.final.contigs.fa.gz.csv
sourmash gather queries/spades.scaffolds.fasta.gz.sig
database.zip -o spades.scaffolds.fasta.gz.csv
pero entonces su tiempo de cómputo total sería la suma de los tiempos de cómputo individuales. ¿Y si cada consulta es súper lenta y/o grande, y tienes docenas o cientos de ellas? ¿ENTONCES QUE?
¡Sigue leyendo!
Automatización y paralelización
1. Escriba un script de shell.
Comencemos por automatizar las consultas para que solo pueda ejecutar un comando y hacer que realice las tres (o N) consultas.
Cree el siguiente script de shell:
run1.sh
:
sourmash gather queries/idba.scaffold.fa.gz.sig database.zip -o idba.scaffold.fa.gz.csv
sourmash gather queries/megahit.final.contigs.fa.gz.sig database.zip -o megahit.final.contigs.fa.gz.csv
sourmash gather queries/spades.scaffolds.fasta.gz.sig database.zip -o spades.scaffolds.fasta.gz.csv
y ejecutarlo:
Esto automatiza los comandos, pero nada más.
Notas:
- todos sus comandos se ejecutarán en serie, uno tras otro;
- el uso de memoria del script será el mismo que el uso de memoria del comando más grande;
2. Agregue un bucle for a su script de shell.
Hay mucha duplicación en el script anterior. La duplicación conduce a errores tipográficos, lo que conduce al miedo, la ira, el odio y el sufrimiento.
Hagamos un guion run2.sh
que contiene un bucle for en su lugar.
run2.sh
:
for query in queries/*.sig
do
output=$(basename $query .sig).csv
sourmash gather $query database.zip -o $output
done
Si bien esto hace exactamente lo mismo computacionalmente como run1.sh
es un poco mejor porque es menos repetitivo y te permite ejecutar tantas consultas como tengas.
Notas:
- sí, estructuramos cuidadosamente los nombres de archivo para que el
for
el bucle funcionaría 🙂 - el
output=
usos de líneabasename
para quitar elqueries/
prefijo y.sig
sufijo de cada nombre de archivo de consulta.
3. Escriba un bucle for que cree un script de shell.
A veces es agradable generar un script que puede editar para ajustar y personalizar los comandos. ¡Probemos eso!
En el indicador de shell, ejecute
for query in queries/*.sig
do
output=$(basename $query .sig).csv
echo sourmash gather $query database.zip -o $output
done > run3.sh
Esto crea un archivo run3.sh
que contiene los comandos a ejecutar. Neato! Ahora puede editar este archivo si desea cambiar individualmente los comandos. O bien, puede ajustar el bucle for si desea cambiar todo los comandos
Notas:
- mismos parámetros de tiempo de ejecución que el anterior: todo se ejecuta en serie.
- cuidado con sobrescribir
run3.sh
¡por accidente después de haberlo editado!
4. Uso parallel
para ejecutar los comandos en su lugar.
Una vez que tengamos este archivo de script listo, podemos ejecutar los comandos en paralelo, usando
ÑU parallel
:
Esto ejecuta hasta dos comandos desde run3.sh
a la vez (-j 2
). Genial, ¿verdad?
Notas:
- dependiendo del parámetro a
-j
esto puede ser mucho más rápido – ¡aquí, el doble de rápido! - también usará el doble de memoria…!
parallel
ejecuta cada línea por sí sola. Entonces, si tiene varias cosas que desea ejecutar en cada sesión paralela, debe hacer algo diferente, como escribir un script de shell para realizar cada acción de cómputo, y entonces ejecutarlos en paralelo.
5. Escriba un segundo script de shell que tome un parámetro.
Cambiemos las cosas: escribamos un script de shell genérico que haga el cálculo. ¡Tenga en cuenta que es el mismo conjunto de comandos que en los bucles for anteriores!
do-gather.sh
:
output=$(basename $1 .sig).csv
sourmash gather $1 database.zip -o $output
Ahora puedes ejecutar esto en un bucle así:
for i in queries/*.sig
do
bash do-gather.sh $i
done
Notas:
- aquí,
$1
es el primer parámetro de la línea de comandos después del nombre del script de shell. - esto es volver al procesamiento en serie, no en paralelo.
Sería fácil convertir esto en algo que pueda ejecutar en paralelo, proporcionando una lista de do-gather.sh
comandos como en (4), arriba.
6. Cambie el segundo script de shell para que sea un script de muestra.
Suponga que tiene acceso a un HPC que tiene muchas computadoras diferentes y desea ejecutar un montón de trabajos grandes al otro lado de esas computadoras. ¿Como hacemos eso?
Todos (¿la mayoría?) de los clústeres tienen un sistema de colas; el nuestro se llama slurm. (Puedes ver un tutorial aquí.)
Para enviar trabajos a muchas computadoras diferentes, puede escribir un script de shell que ejecute un trabajo en particular y luego ejecutar muchos de esos.
Cambiar do-gather.sh
para parecerse a lo siguiente.
#SBATCH -c 1 # cpus per task
#SBATCH --mem=5Gb # memory needed
#SBATCH --time=00-00:05:00 # time needed
#SBATCH -p med2
output=$(basename $1 .sig).csv
sourmash gather $1 database.zip -o $output
Este es ahora un script que puede enviar al HPC para que lo ejecute, usando sbatch
:
for i in queries/*.sig
do
sbatch do-gather.sh $i
done
La ventaja aquí es que HPC puede programar estos comandos para que se ejecuten cuando y donde haya “espacio” computacional para ejecutarlos. (Aquí el #SBATCH
Las líneas en el script de shell especifican cuánto tiempo de cómputo/memoria se necesita).
Notas:
- esto distribuye su trabajo a través del HPC;
- ¡estos trabajos solo ocupan tanto tiempo/memoria como cada trabajo individualmente! ¡pero ahora se ejecutan en paralelo en varias máquinas!
do-gather.sh
en realidad sigue siendo un script bash, por lo que también puede ejecutarlo de esa manera.
7. Escriba un archivo de creación de serpientes.
Una alternativa a todo lo anterior es hacer que Snakemake ejecute las cosas por usted. Aquí hay un archivo de serpiente simple para ejecutar cosas en paralelo:
Snakefile
:
QUERY, = glob_wildcards("queries/.sig")
rule all:
input:
expand(".csv", q=QUERY)
rule run_query:
input:
sig = "queries/.sig",
output:
csv = ".csv"
shell: """
sourmash gather database.zip -o
"""
y ejecutarlo en paralelo:
Notas:
- esto ejecutará las cosas en paralelo como en el ejemplo anterior (4).
Estrategias de prueba y evaluación
Estas son las tres estrategias que uso cuando trato de escalar algo para ejecutarlo en múltiples trabajos y en múltiples computadoras:
- Construir alrededor de un ejemplo existente.
- Submuestree los datos de su consulta.
- Prueba en una versión más pequeña de tu problema.
Apéndice: hacer que sus scripts de shell sean más agradables
¡Los scripts de shell anteriores no son en realidad la forma en que recomiendo escribir scripts de shell! Aquí hay algunos pensamientos adicionales para usted:
1. Hágalos ejecutables sin un explícito bash
Poner #! /bin/bash
en la parte superior del script de shell y ejecute chmod +x <scriptname>
y ahora podrás ejecutarlos directamente:
2. Establecer salida de error
Agregar set -e
en la parte superior de su script de shell y dejará de ejecutarse cuando haya un error.