我有一个用numba编写的相当大的代码库,我注意到当为另一个文件中调用另一个numba编译函数的函数启用缓存时,调用被调用函数时不会调用被调用函数的变化。当我有两个文件时会出现这种情况:
testfile2:
import numba
@numba.njit(cache=True)
def function1(x):
return x * 10
testfile的:
import numba
from tests import file1
@numba.njit(cache=True)
def function2(x, y):
return y + file1.function1(x)
如果在jupyter笔记本中,我运行以下内容:
# INSIDE JUPYTER NOTEBOOK
import sys
sys.path.insert(1, "path/to/files/")
from tests import testfile
testfile.function2(3, 4)
>>> 34 # good value
但是,如果我更改,则将testfile2更改为以下内容:
import numba
@numba.njit(cache=True)
def function1(x):
return x * 1
然后我重新启动jupyter笔记本内核并重新运行笔记本,我得到以下内容
import sys
sys.path.insert(1, "path/to/files/")
from tests import testfile
testfile.function2(3, 4)
>>> 34 # bad value, should be 7
将两个文件导入笔记本对不良结果没有影响。此外,仅在cache=False
上设置function1
也无效。什么工作是在所有njit'ted函数上设置cache=False
,然后重新启动内核,然后重新运行。
我相信LLVM可能会内联一些被调用的函数,然后再也不会再检查它们了。
我查看了源代码并发现有一个方法返回缓存对象numba.caching.NullCache()
,实例化缓存对象并运行以下内容:
cache = numba.caching.NullCache()
cache.flush()
不幸的是,似乎没有效果。
是否存在numba环境设置,或者我可以手动清除conda env中所有缓存函数的其他方式?或者我只是做错了什么?
我在Mac OS X 10.12.3上使用Anaconda Python 3.6运行numba 0.33。
答案 0 :(得分:2)
这有点像黑客,但它是我以前用过的东西。如果你把这个函数放在你的numba函数的顶层(对于这个例子,在testfile
中),它应该重新编译所有东西:
import inspect
import sys
def recompile_nb_code():
this_module = sys.modules[__name__]
module_members = inspect.getmembers(this_module)
for member_name, member in module_members:
if hasattr(member, 'recompile') and hasattr(member, 'inspect_llvm'):
member.recompile()
然后在您想要强制重新编译时从您的jupyter笔记本中调用它。需要注意的是,它只适用于此函数所在模块中的文件及其依赖项。可能有另一种方式来概括它。
答案 1 :(得分:1)
在看到Josh的答案之后,通过在项目方法中创建一个实用程序来杀死缓存,我用一个黑客解决方案解决了这个问题。
可能有更好的方法,但这有效。我打开这个问题,万一有人不那么讨厌这样做。
import os
def kill_files(folder):
for the_file in os.listdir(folder):
file_path = os.path.join(folder, the_file)
try:
if os.path.isfile(file_path):
os.unlink(file_path)
except Exception as e:
print("failed on filepath: %s" % file_path)
def kill_numba_cache():
root_folder = os.path.realpath(__file__ + "/../../")
for root, dirnames, filenames in os.walk(root_folder):
for dirname in dirnames:
if dirname == "__pycache__":
try:
kill_files(root + "/" + dirname)
except Exception as e:
print("failed on %s", root)