Snakemake:使用校验和而不是时间戳?
Snakemake: use checksums instead of timestamps?
我的项目很可能存在输入数据集被覆盖但内容未更改的情况。 Snakemake 中有没有一种方法可以使用校验和而不是时间戳来检查构建更改?
例如,Scons 使用 md5 散列(仅在时间戳已更改的地方计算散列)检查代码和数据中的构建更改。但我更喜欢使用 Snakemake,因为它还有其他杀手级功能。
所需的行为类似于文档中描述的 between workflow caching 功能。在文档中它说:
There is no need to use this feature to avoid redundant computations within a workflow. Snakemake does this already out of the box.
但所有对此问题的引用都指向 Snakemake 仅在正常工作流程中使用时间戳。
使用 ancient
标记或使用 touch
来调整时间戳对我来说不起作用,因为这需要太多的手动干预。
我最终发现 an old SO post 表明我可以通过编写自己的脚本来比较校验和然后将其输入 Snakemake 来做到这一点,但我不确定这是否仍然是唯一的选择。
我不知道 snakemake 中有内置解决方案。也许这就是我的处理方式。
假设您的输入数据是 data.txt
。这是可能未更改而被覆盖的文件。不是直接在 snakemake rules
中使用这个文件,而是使用一个缓存的副本,只有当 md5 在原始文件和缓存之间发生变化时才会被覆盖。可以使用标准 python 代码在 rule all
之前完成检查。
这是一个伪代码示例:
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
但是,这增加了管道的复杂性,所以我会检查它是否值得。
我的项目很可能存在输入数据集被覆盖但内容未更改的情况。 Snakemake 中有没有一种方法可以使用校验和而不是时间戳来检查构建更改?
例如,Scons 使用 md5 散列(仅在时间戳已更改的地方计算散列)检查代码和数据中的构建更改。但我更喜欢使用 Snakemake,因为它还有其他杀手级功能。
所需的行为类似于文档中描述的 between workflow caching 功能。在文档中它说:
There is no need to use this feature to avoid redundant computations within a workflow. Snakemake does this already out of the box.
但所有对此问题的引用都指向 Snakemake 仅在正常工作流程中使用时间戳。
使用 ancient
标记或使用 touch
来调整时间戳对我来说不起作用,因为这需要太多的手动干预。
我最终发现 an old SO post 表明我可以通过编写自己的脚本来比较校验和然后将其输入 Snakemake 来做到这一点,但我不确定这是否仍然是唯一的选择。
我不知道 snakemake 中有内置解决方案。也许这就是我的处理方式。
假设您的输入数据是 data.txt
。这是可能未更改而被覆盖的文件。不是直接在 snakemake rules
中使用这个文件,而是使用一个缓存的副本,只有当 md5 在原始文件和缓存之间发生变化时才会被覆盖。可以使用标准 python 代码在 rule all
之前完成检查。
这是一个伪代码示例:
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
但是,这增加了管道的复杂性,所以我会检查它是否值得。