Kategorie: Know-how

  • Parallele Jobs in Snakemake mit Ressourcen begrenzen

    Einleitung

    Bei rechenintensiven Workflows mit Snakemake kann es passieren, dass zu viele Jobs parallel laufen und übermäßige I/O-Last, Speicherdruck oder hohe Latenz auf der Festplatte verursachen. Das kann zu fehlgeschlagenen Jobs oder schlechter Leistung führen.

    Snakemake bietet mit der Direktive resources eine Möglichkeit, die parallele Ausführung pro Regel zu begrenzen; das funktioniert aber nur, wenn man beim Ausführen des Workflows auch ein globales Ressourcenlimit angibt.

    In diesem Beitrag zeige ich, wie man die Zahl paralleler Jobs für eine bestimmte Regel mit dem Ressourcenmanagement von Snakemake richtig begrenzt.


    Das Problem: Zu viele Jobs gleichzeitig

    Nehmen wir folgende Snakemake-Regel:

    rule process_data:
        input:
            "{sample}.raw"
        output:
            "{sample}.processed"
        resources:
            process_data_jobs=1  # Assign a resource unit for limiting the number of jobs
        shell:
            """
            some_tool --input {input} --output {output}
            """

    Warum begrenzt resources allein die Ausführung nicht?

    Man könnte erwarten, dass resources: processing_jobs=1 Snakemake automatisch auf einen Job gleichzeitig beschränkt. Snakemake plant aber nicht nach Ressourcen, solange man beim Start des Workflows kein globales Limit angibt.

    Ohne globales Limit startet Snakemake womöglich trotzdem zu viele Jobs parallel und überlastet das System.


    Die Lösung: Ressourcenlimits durchsetzen

    Um die Zahl paralleler Jobs tatsächlich zu begrenzen, startet man Snakemake mit:

    snakemake --resources process_data_jobs=10

    Wie funktioniert das?

    • Jeder Job von process_data fordert 1 Einheit von process_data_jobs an.
    • Das globale Limit processing_jobs=10 sorgt dafür, dass höchstens 10 Jobs (10 / 1 = 10) parallel laufen. Man kann auch andere Einheiten wählen, wenn man möchte

    Vor dem Limit liefen teils viel zu viele Jobs gleichzeitig! Danach durften nur noch 10 Jobs parallel laufen.


    Fazit

    Wer in Snakemake mit hoher Festplattenlatenz, I/O-Druck oder zu vielen gleichzeitigen Jobs kämpft, bekommt das am besten in den Griff, indem er:

    1. mit resources die Ressourcen pro Job festlegt.
    2. beim Ausführen von Snakemake ein globales Ressourcenlimit setzt (--resources processing_jobs=10).

    So läuft der Workflow effizient und zuverlässig, ohne das System zu überlasten!

  • Dateien in meinen Ordnern zählen

    Speicherplatz effizient zu verwalten ist wichtig, besonders auf Systemen mit strengen Datei-Kontingenten. Neulich hatte ich mein Dateilimit überschritten und brauchte schnell einen Weg herauszufinden, welche Ordner die meisten Dateien enthalten. Um meine Speichernutzung zu analysieren, habe ich folgenden Befehl verwendet:

    for d in .* *; do [ -d "$d" ] && echo "$d: $(find "$d" -type f | wc -l)"; done | sort -nr -k2

    Der Befehl im Einzelnen

    Dieser Einzeiler zählt effizient die Dateien in allen Verzeichnissen am aktuellen Ort, auch in versteckten. So funktioniert er:

    • for d in .* * – läuft über alle Dateien und Verzeichnisse, auch versteckte.
    • [ -d "$d" ] – sorgt dafür, dass nur Verzeichnisse verarbeitet werden.
    • find "$d" -type f | wc -l – zählt alle Dateien (keine Verzeichnisse) in jedem Ordner, einschließlich Unterverzeichnissen.
    • sort -nr -k2 – sortiert die Ergebnisse absteigend nach Anzahl der Dateien.

    Wozu das nützt

    Mit diesem Befehl habe ich schnell die Verzeichnisse gefunden, die die meisten Inodes belegen, und konnte etwas tun, etwa unnötige Dateien aufräumen. Eine effiziente Methode, um die Verteilung der Dateien zu verstehen und Speichergrenzen im Griff zu behalten.

    Alternativen

    Wer nur die Dateien direkt in jedem Ordner zählen möchte (ohne Unterverzeichnisse), kann den Befehl so abwandeln:

    for d in .* *; do [ -d "$d" ] && echo "$d: $(find "$d" -maxdepth 1 -type f | wc -l)"; done | sort -nr -k2

    Diese Variante ist nützlich, wenn man einen eher örtlichen Blick auf die Dateiverteilung braucht.

  • Eine fehlgeschlagene R-Paket-Installation ließ sich nicht löschen

    Heute ist mir etwas Seltsames passiert, als ich ein Update für eines meiner R-Pakete installieren wollte. Wie üblich habe ich die neueste Version so installiert

    library("devtools")
    install_github("fischuu/GenomicTools")

    Die Installation schlug aber fehl, und als ich sie wiederholen wollte, kam diese Fehlermeldung:

    Installing package into ‘/homeappl/home/<user>/R/x86_64-redhat-linux-gnu-library/4.1’
    (as ‘lib’ is unspecified)
    ERROR: failed to lock directory ‘/homeappl/home/<user>/R/x86_64-redhat-linux-gnu-library/4.1’ for modifying
    Try removing ‘/homeappl/home/<user>/R/x86_64-redhat-linux-gnu-library/4.1/00LOCK-GenomicTools’
    Warning message:
    In i.p(...) :
      installation of package ‘/tmp/Rtmp<...>Lv/file3c36<...>34/GenomicTools_0.2.11.tar.gz’ had non-zero exit status

    Also bin ich in das genannte Verzeichnis gegangen, um den Ordner von Hand zu löschen, und bekam dort einen weiteren Fehler:

    rm: cannot remove '00LOCK-GenomicTools/GenomicTools/libs/.nfs00000001002e2<...>d': Device or resource busy

    Ich habe dies und das versucht, aber nichts half, den Ordner zu löschen; er meldete mir hartnäckig, dass das Gerät beschäftigt sei. Am Ende half nur, den Ordner umzubenennen, etwa so

    mv 00LOCK-GenomicTools/ 00LOCK-GenomicTools-deleteThis/

    Er hängt jetzt immer noch im Ordner herum, aber ich konnte das R-Paket neu installieren. In ein paar Tagen schaue ich wieder nach, ob das Gerät noch beschäftigt ist oder ob ich ihn dann löschen kann …

  • Git-Submodule

    Heute bin ich zum ersten Mal auf das Konzept der Submodule in Git gestoßen. Beim Klonen eines Repositorys von GitHub fiel mir auf, dass ein Ordner darin leer blieb. Bei genauerem Hinsehen fand ich einen Verweis auf einen anderen Repository-Baum, etwa so:

    Hier stammt der Ordner htslib eigentlich aus einem Baum in einem anderen Repository. Nachdem ich das Repository so geklont hatte (vorher geforkt):

    git clone https://github.com/fischuu/SE-MEI.git

    blieb der Ordner htslib leer. Das liegt daran, dass Dateien aus Submodulen standardmäßig nicht geholt werden. Das muss man separat machen, indem man zuerst die Submodule initialisiert (vorher ins geklonte Repository wechseln)

    git submodule init

    und dann deren Dateien aktualisiert

    git submodule update

    Danach sollte das Repository vollständig sein. Statt die Submodule separat zu initialisieren, gibt es auch eine Abkürzung, die alles in einem Schritt holt, indem man beim Klonen einen zusätzlichen Parameter angibt, etwa so:

    git clone --recurse-submodules https://github.com/fischuu/SE-MEI.git

    Mehr Details zu Git-Submodulen gibt es hier.

  • Eine externe Festplatte in die fstab eintragen

    Um eine externe Festplatte dauerhaft einzubinden, ermittelt man am besten zuerst die UUID und das zugehörige Dateisystem mit

    sudo blkid

    Mit diesen Angaben bearbeitet man die fstab

    sudo vim /etc/fstab

    und trägt dort eine Zeile in diesem Format ein

    UUID=<UUID> \tab <mountPoint> \tab <filesystem> \tab <options> \tab 0 \tab 1

    Die Werte für <UUID> und <filesytem> liefert der Befehl blkid, den Einhängepunkt kann man frei wählen, und als Option nehme ich z. B. errors=remount-ro

    Ist die fstab so ergänzt, einfach versuchen, die Platte einzuhängen mit

    sudo mount -a