챕터 4 - 규칙을 병렬로 실행하기

이전 Snakefile에서 sketch_genomes 규칙을 다시 살펴봅시다:

rule sketch_genomes:
    output:
        "GCF_000017325.1.fna.gz.sig",
        "GCF_000020225.1.fna.gz.sig",
        "GCF_000021665.1.fna.gz.sig"
    shell: """
        sourmash sketch dna -p k=31 genomes/*.fna.gz --name-from-first
    """

rule compare_genomes:
    input:
        "GCF_000017325.1.fna.gz.sig",
        "GCF_000020225.1.fna.gz.sig",
        "GCF_000021665.1.fna.gz.sig"
    output:
        "compare.mat"
    shell: """
        sourmash compare {input} -o {output}
    """

rule plot_comparison:
    message: "sourmash로 모든 입력 게놈을 비교합니다"
    input:
        "compare.mat"
    output:
        "compare.mat.matrix.png"
    shell: """
        sourmash plot {input}
    """

현재 이 코드는 잘 작동하지만, 약간 불편한 점이 있습니다. 생물정보학 분야의 특성상 나중에 비교에 더 많은 게놈을 추가하고 싶을 때가 생기는데, 지금은 추가할 게놈마다 inputoutput 양쪽에 이름을 추가해야 합니다. 크게 어렵진 않지만 불필요한 반복 작업입니다.

또한 게놈이 매우 많아지면 이 단계가 병목 구간이 될 수 있습니다. sourmash sketch는 게놈 10~20개에서는 빠르게 실행되지만, 100개나 1000개가 되면 느려집니다! (실제로 sourmash sketch는 게놈 1개에 비해 100개에서 약 100배 더 오래 걸립니다.) 속도를 높이는 방법이 있을까요?

있습니다! 각 게놈에 대해 개별적으로 실행할 수 있는 규칙을 작성하고, Snakemake가 이를 병렬로 실행하도록 요청하면 됩니다!

참고: 경우에 따라 모든 게놈을 하나의 규칙에서 처리해야 할 수도 있습니다. 예를 들어 compare_genomes모든 게놈을 비교해야 하므로 이를 피할 방법이 없습니다. 하지만 sketch_genomes는 간단한 대안이 있습니다!

한 규칙을 세 개의 별도 규칙으로 나누는 것부터 시작해 봅시다:

rule sketch_genomes_1:
    input:
        "genomes/GCF_000017325.1.fna.gz",
    output:
        "GCF_000017325.1.fna.gz.sig",
    shell: """
        sourmash sketch dna -p k=31 {input} \
            --name-from-first
    """

rule sketch_genomes_2:
    input:
        "genomes/GCF_000020225.1.fna.gz",
    output:
        "GCF_000020225.1.fna.gz.sig",
    shell: """
        sourmash sketch dna -p k=31 {input} \
            --name-from-first
    """

rule sketch_genomes_3:
    input:
        "genomes/GCF_000021665.1.fna.gz",
    output:
        "GCF_000021665.1.fna.gz.sig"
    shell: """
        sourmash sketch dna -p k=31 {input} \
            --name-from-first
    """

rule compare_genomes:
    input:
        "GCF_000017325.1.fna.gz.sig",
        "GCF_000020225.1.fna.gz.sig",
        "GCF_000021665.1.fna.gz.sig"
    output:
        "compare.mat"
    shell: """
        sourmash compare {input} -o {output}
    """

rule plot_comparison:
    message: "sourmash로 모든 입력 게놈을 비교합니다"
    input:
        "compare.mat"
    output:
        "compare.mat.matrix.png"
    shell: """
        sourmash plot {input}
    """

코드가 많아 보이지만 잘 작동합니다. 다음을 실행해 확인해 보세요:

snakemake -j 1 --delete-all plot_comparison
snakemake -j 1 plot_comparison

파일을 더 수정하기 전에, 이 작업의 결실을 즐겨봅시다. 이제 Snakemake에게 여러 규칙을 동시에 실행하도록 요청할 수 있습니다!

다음을 입력해 보세요:

snakemake -j 1 --delete-all plot_comparison
snakemake -j 3 plot_comparison

자세히 살펴보면, Snakemake가 sourmash sketch dna 명령 세 개를 동시에 실행하는 것을 볼 수 있습니다.

이것은 정말 멋진 기능이며 Snakemake의 강력한 실용적 특징 중 하나입니다. Snakemake에게 무엇을 원하는지(대상 지정)와 각 단계를 어떻게 수행할지(레시피 제공)를 알려주면, Snakemake가 주어진 자원으로 모든 필요한 단계를 가장 빠르게 실행하는 방법을 스스로 찾아냅니다.

이 경우 -j 3으로 한 번에 최대 세 개의 작업을 실행할 수 있다고 Snakemake에게 알려주었습니다. 더 많은 작업을 동시에 실행하도록 지정할 수도 있지만, 현재는 동시에 실행할 수 있는 규칙이 세 개뿐입니다. sketch_genomes_1, sketch_genomes_2, sketch_genomes_3가 바로 그것입니다. compare_genomes 규칙은 이 세 규칙의 출력이 필요하고, plot_genomes 역시 compare_genomes의 출력이 필요하기 때문에 다른 규칙과 동시에 실행될 수 없습니다!