首页 > 解决方案 > Snakemake:使用校验和而不是时间戳?

问题描述

我的项目可能存在输入数据集被覆盖但内容未更改的情况。Snakemake 中有没有办法使用校验和而不是时间戳来检查构建更改?

例如,Scons 使用 md5 哈希检查代码和数据中的构建更改(仅在时间戳发生更改时计算哈希)。但我更喜欢使用 Snakemake,因为它还有其他杀手级功能。

所需的行为类似于文档中描述的工作流缓存功能之间的行为。在文档中它说:

无需使用此功能来避免工作流中的冗余计算。Snakemake 开箱即用。

但是所有对这个问题的引用都指向 Snakemake 仅在正常工作流程中使用时间戳。

使用ancient标记或使用touch来调整时间戳对我来说不起作用,因为这需要太多的手动干预。

我最终找到了一篇旧的 SO 帖子,表明我可以通过编写自己的脚本来比较校验和然后将其输入 Snakemake 来做到这一点,但我不确定这是否仍然是唯一的选择。

标签: snakemake

解决方案


我不知道snakemake 中的内置解决方案。也许这就是我将如何去做。

假设您的输入数据是data.txt. 这是可能在不更改的情况下被覆盖的文件。不是直接在snakemake中使用这个文件rules,而是使用一个缓存副本,只有当md5在原始和缓存之间发生变化时才会被覆盖。检查可以在rule all使用标准 python 代码之前完成。

这是一个伪代码示例:

input_md5 = get_md5('data.txt')
cache_md5 = get_md5('cache/data.txt')

if input_md5 != cache_md5:
    # This will trigger the pipeline because cache/data.txt is newer than output
    copy('data.txt', 'cache/data.txt') 

rule all:
    input:
        'stuff.txt'

rule one:
    input:
        'cache/data.txt',
    output:
        'stuff.txt',

编辑:这个伪代码保存了缓存输入文件的 md5,所以它们不需要每次都重新计算。它还将输入数据的时间戳保存到文件中,以便仅当此类时间戳比缓存的时间戳更新时才重新计算输入的 md5:

for each input datafile do:

current_input_timestamp = get_timestamp('data.txt')
cache_input_timestamp = read('data.timestamp.txt')

if current_input_timestamp > cache_input_timestamp:
    input_md5 = get_md5('data.txt')
    cache_md5 = read('cache/data.md5')

    if input_md5 != cache_md5:
        copy('data.txt', 'cache/data.txt') 
        write(input_md5, 'cache/data.md5')
        write(current_input_timestamp, 'data.timestamp.txt')

# If any input datafile is newer than the cache, the pipeline will be triggered

然而,这增加了管道的复杂性,所以我会检查它是否值得。


推荐阅读