缓存¶
在许多情况下,Bodo 可以将函数编译生成的二进制文件保存到磁盘,以便在未来的运行中重用。这避免了下次运行应用程序时重新编译函数的需要。
仅在使用新输入类型调用函数时,才有必要重新编译函数,缓存也适用同样的原则。换句话说,如果数据类型保持不变(这是最常见的情况),则可以多次运行一个应用程序并处理不同的数据,而不必重新编译任何代码。
警告
缓存在大多数(但不是全部)情况下有效,并且默认情况下是禁用的。有关更多信息,请参阅下方的缓存限制。
缓存示例¶
要缓存一个函数,我们只需要将选项 cache=True 添加到 JIT 装饰器中:
import time
import pandas as pd
import bodo
@bodo.jit(cache=True)
def mean_power_speed():
df = pd.read_parquet("data/cycling_dataset.pq")
return df[["power", "speed"]].mean()
t0 = time.time()
result = mean_power_speed()
print(result)
print("Total execution time:", round(time.time() - t0, 3), "secs")
上述代码第一次运行时,Bodo 编译该函数并将其缓存到磁盘。该代码计算整个函数调用的时间,这包括第一次运行函数时的编译时间:
在后续运行中,它将从缓存中恢复函数,因此执行时间将大大缩短:注意
data/cycling_dataset.pq 位于 Bodo 教程 repo 中。
缓存位置和可移植性¶
在大多数情况下,缓存保存在源文件所在目录中的 __pycache__ 目录中。可以将变量 NUMBA_DEBUG_CACHE 设置为 1,以查看缓存的确切位置以及是否正在写入或读取。
在Jupyter笔记本中,缓存目录被称为 numba_cache,位于 IPython.paths.get_ipython_cache_dir()。有关这些和其他备用缓存位置的更多信息,请参见 here。例如,在笔记本中运行时:
import os
import IPython
cache_dir = IPython.paths.get_ipython_cache_dir() + "/numba_cache"
print("Cache files:")
os.listdir(cache_dir)
Cache files:
['ipython-input-bce41f829e09.mean_power_speed-4444615264.py38.nbi',
'ipython-input-bce41f829e09.mean_power_speed-4444615264.py38.1.nbc']
缓存对象在具有相同CPU型号和CPU特征的系统之间有效。因此,在不同机器上共享和重用缓存目录中的内容是安全的。有关更多信息,请参见这里。
缓存失效¶
当相应的源代码被修改时,缓存会自动失效。观察这种行为的一种方法是,在首次缓存后修改上述示例,改变变量名 df。下次运行代码时,Bodo 将确定源代码已被修改,失效缓存并重新编译该函数。
警告
有时需要手动清除缓存(请参见下面的缓存限制)。要清除缓存,只需删除缓存文件。
重用缓存的提示¶
如上所述,缓存会在文件中任何源代码发生变化时使函数失效。如果我们在同一个文件中定义一个函数并调用它,并修改传递给函数的参数,缓存将会失效。
缓存文件输入输出¶
例如:一个典型的使用案例是调用一个输入输出函数,使用不同的文件名。
如果io_call的参数从mydata.parquet发生更改,则需要对上述函数进行重新编译。通过将函数调用与函数定义分开,函数定义不需要针对每个具有新参数的函数调用进行重新编译。缓存的IO函数将在文件名称发生更改时工作,只要文件模式相同。例如,下面的代码片段
每次 file_name 被修改时,不需要重新编译 IO_function,因为 IO_function 与该代码更改是隔离的。
缓存笔记本单元格¶
对于IPython笔记本,应该将要缓存的函数与函数调用放在不同的单元格中。
如果一个包含缓存函数的单元格被修改,那么它的缓存将失效,函数必须重新编译。
当前缓存限制¶
- 编译函数的更改在不同文件之间是不可见的。比如,如果我们有一个缓存的 Bodo 函数,该函数调用了一个在不同文件中的缓存 Bodo 函数,并且修改了后者,那么 Bodo 将不会更新其缓存(因此将使用该函数的旧版本运行)。
- 全局变量被视为编译时常量。当一个 函数被编译时,函数使用的任何全局变量的值将在编译时嵌入到二进制文件中,并保持不变。如果全局变量的值在编译后在源代码中发生变化,则编译后的对象(和缓存)将不会重新绑定到新值。
故障排除¶
在执行过程中,如果环境变量 NUMBA_DEBUG_CACHE 被设置为 1,Bodo 将会打印缓存信息。例如,在第一次运行时,它将显示缓存是否被保存以及保存的位置,而在随后的运行中,它将显示编译器是否成功从缓存中加载。
如果编译器报告无法缓存一个函数,或者无法从缓存加载一个函数,请在我们的仓库中报告这个问题。