在 Dask 中使用可重用的自定义图形进行机会缓存
Opportunistic caching with reusable custom graphs in Dask
Dask supports defining custom computational graphs as well as opportinistic caching。问题是它们如何一起使用。
例如,让我们定义一个非常简单的计算图,计算x+1
操作,
import dask
def compute(x):
graph = {'step1': (sum, [x, 1])}
return dask.get(graph, 'step1')
print('Cache disabled:', compute(1), compute(2))
这会按预期产生 2
和 3
。
现在我们启用机会缓存,
from dask.cache import Cache
cc = Cache(1e9)
cc.register()
print('Cache enabled: ', compute(1), compute(2))
print(cc.cache.data)
在这两种情况下,我们都错误地得到了 2
的结果,因为 cc.cache.data
是 {'step1': 2}
,与输入无关。
我想这意味着输入需要被散列(例如 dask.base.tokenize
and appended to all the keys in the graph. Is there a simpler way of doing it, particularly since the tokenize function is not part of the public API?
问题在于,在复杂的图形中,随机步骤名称需要考虑提供给其子步骤的所有输入的哈希值,这意味着有必要进行完整的图形解析。
dask 图中的键名必须是唯一的(正如您在上面发现的那样),这一点很重要。此外,我们希望相同的计算具有相同的密钥,这样我们就可以避免多次计算它们——尽管这不是 dask 工作所必需的,它只是提供了一些优化的机会。
在 dask 的内部,我们使用 dask.base.tokenize
来计算输入的 "hash",从而产生确定性的键名。您也可以自由使用此功能。在上面链接的问题中,我们说函数是 public,只是实现可能会改变(不是签名)。
另请注意,对于许多用例,我们建议现在使用 dask.delayed
而不是自定义图形来生成自定义计算。这将在幕后为您进行确定性散列。
Dask supports defining custom computational graphs as well as opportinistic caching。问题是它们如何一起使用。
例如,让我们定义一个非常简单的计算图,计算x+1
操作,
import dask
def compute(x):
graph = {'step1': (sum, [x, 1])}
return dask.get(graph, 'step1')
print('Cache disabled:', compute(1), compute(2))
这会按预期产生 2
和 3
。
现在我们启用机会缓存,
from dask.cache import Cache
cc = Cache(1e9)
cc.register()
print('Cache enabled: ', compute(1), compute(2))
print(cc.cache.data)
在这两种情况下,我们都错误地得到了 2
的结果,因为 cc.cache.data
是 {'step1': 2}
,与输入无关。
我想这意味着输入需要被散列(例如 dask.base.tokenize
and appended to all the keys in the graph. Is there a simpler way of doing it, particularly since the tokenize function is not part of the public API?
问题在于,在复杂的图形中,随机步骤名称需要考虑提供给其子步骤的所有输入的哈希值,这意味着有必要进行完整的图形解析。
dask 图中的键名必须是唯一的(正如您在上面发现的那样),这一点很重要。此外,我们希望相同的计算具有相同的密钥,这样我们就可以避免多次计算它们——尽管这不是 dask 工作所必需的,它只是提供了一些优化的机会。
在 dask 的内部,我们使用 dask.base.tokenize
来计算输入的 "hash",从而产生确定性的键名。您也可以自由使用此功能。在上面链接的问题中,我们说函数是 public,只是实现可能会改变(不是签名)。
另请注意,对于许多用例,我们建议现在使用 dask.delayed
而不是自定义图形来生成自定义计算。这将在幕后为您进行确定性散列。