🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# 1.16。常见问题 > 原文: [http://numba.pydata.org/numba-doc/latest/user/faq.html](http://numba.pydata.org/numba-doc/latest/user/faq.html) ## 1.16.1。编程 ### 1.16.1.1。我可以将函数作为参数传递给 jitted 函数吗? 从 Numba 0.39 开始,你可以,只要函数参数也被 JIT 编译: ```py @jit(nopython=True) def f(g, x): return g(x) + g(-x) result = f(jitted_g_function, 1) ``` 但是,使用作为函数的参数进行调度会产生额外的开销。如果这对您的应用程序很重要,您还可以使用工厂函数来捕获闭包中的函数参数: ```py def make_f(g): # Note: a new f() is created each time make_f() is called! @jit(nopython=True) def f(x): return g(x) + g(-x) return f f = make_f(jitted_g_function) result = f(1) ``` 提高 Numba 功能的调度性能是一项持续的任务。 ### 1.16.1.2。当我修改全局变量 时,Numba 似乎并不关心 Numba 将全局变量视为编译时常量。如果您希望在修改全局变量值时自己的 jitted 函数自行更新,一种解决方案是使用 [`recompile()`](../reference/jit-compilation.html#Dispatcher.recompile "Dispatcher.recompile") 方法重新编译它。但这是一个相对较慢的操作,因此您可以决定重新构建代码并将全局变量转换为函数参数。 ### 1.16.1.3。我可以调试 jitted 功能吗? Numba 编译的代码目前不支持调用 [`pdb`](https://docs.python.org/3/library/pdb.html#module-pdb "(in Python v3.7)") 或其他此类高级设施。但是,您可以通过设置 [`NUMBA_DISABLE_JIT`](../reference/envvars.html#envvar-NUMBA_DISABLE_JIT) 环境变量来暂时禁用编译。 ### 1.16.1.4。如何创建 Fortran 排序的数组? Numba 目前不支持大多数 Numpy 函数的`order`参数,例如 [`numpy.empty()`](https://docs.scipy.org/doc/numpy/reference/generated/numpy.empty.html#numpy.empty "(in NumPy v1.16)") (由于[类型推断](../glossary.html#term-type-inference)算法的限制)。您可以通过创建 C 有序数组然后转置它来解决此问题。例如: ```py a = np.empty((3, 5), order='F') b = np.zeros(some_shape, order='F') ``` 可以改写为: ```py a = np.empty((5, 3)).T b = np.zeros(some_shape[::-1]).T ``` ### 1.16.1.5。如何增加整数宽度? 默认情况下,Numba 通常使用整数变量的机器整数宽度。在 32 位机器上,您有时可能需要 64 位整数的大小。您可以简单地将相关变量初始化为`np.int64`(例如`np.int64(0)`而不是`0`)。它将传播到涉及这些变量的所有计算。 ### 1.16.1.6。如何判断`parallel=True`是否有效? 将[环境变量](../reference/envvars.html#numba-envvars) `NUMBA_WARNINGS`设置为非零,如果`parallel=True`转换因装饰的功能失败,将显示警告。 此外,设置[环境变量](../reference/envvars.html#numba-envvars) `NUMBA_DEBUG_ARRAY_OPT_STATS`将显示有关哪些运算符/调用转换为并行 for 循环的一些统计信息。 ## 1.16.2。表现 ### 1.16.2.1。 Numba 内联功能吗? Numba 为 LLVM 提供了足够的信息,因此可以内联足够短的函数。这仅适用于 [nopython 模式](../glossary.html#term-nopython-mode)。 ### 1.16.2.2。 Numba 矢量化阵列计算(SIMD)吗? Numba 本身并没有实现这样的优化,但它允许 LLVM 应用它们。 ### 1.16.2.3。为什么我的循环没有矢量化? Numba 默认启用 LLVM 中的循环向量化优化。虽然它是一个强大的优化,但并非所有循环都适用。有时,循环向量化可能会因内存访问模式等细微细节而失败。要从 LLVM 查看其他诊断信息,请添加以下行: ```py import llvmlite.binding as llvm llvm.set_option('', '--debug-only=loop-vectorize') ``` 这告诉 LLVM 从 **loop-vectorize** 传递到 stderr 打印调试信息。每个函数条目如下所示: ```py LV: Checking a loop in "<low-level symbol name>" from <function name> LV: Loop hints: force=? width=0 unroll=0 ... LV: Vectorization is possible but not beneficial. LV: Interleaving is not beneficial. ``` 每个函数条目由空行分隔。拒绝矢量化的原因通常是在条目结束时。在上面的示例中,LLVM 拒绝了矢量化,因为这样做不会加速循环。在这种情况下,它可能是由于内存访问模式。例如,循环的数组可能不是连续的布局。 当内存访问模式不重要,无法确定访问内存区域时,LLVM 可能会拒绝以下消息: ```py LV: Can't vectorize due to memory conflicts ``` 另一个常见原因是: ```py LV: Not vectorizing: loop did not meet vectorization requirements. ``` 在这种情况下,矢量化被拒绝,因为矢量化代码可能表现不同。这是尝试打开`fastmath=True`以允许 fastmath 指令的情况。 ### 1.16.2.4。 Numba 会自动并行化代码吗? 在某些情况下,它可以: * 具有`target="parallel"`选项的 Ufuncs 和 gufunc 将在多个线程上运行。 * `@jit`的`parallel=True`选项将尝试优化阵列操作并并行运行。它还增加了对`prange()`的支持,以显式并行化循环。 您也可以自己在多个线程上手动运行计算并使用`nogil=True`选项(参见[释放 GIL](jit.html#jit-nogil) )。 Numba 还可以使用其 CUDA 和 HSA 后端在 GPU 架构上实现并行执行。 ### 1.16.2.5。 Numba 可以加快短期运行功能吗? 不显着。新用户有时希望 JIT 编译这样的函数: ```py def f(x, y): return x + y ``` 并获得 Python 解释器的显着加速。但是 Numba 没有太多可以改进的地方:大部分时间都可能花在 CPython 的函数调用机制上,而不是函数本身。根据经验,如果函数执行时间不到 10μs:请保留它。 例外情况是你应该 JIT 编译该函数,如果它是从另一个 jitted 函数调用的。 ### 1.16.2.6。当 JIT 编译一个复杂的函数时有一个延迟,我该如何改进呢? 尝试将`cache=True`传递给`@jit`装饰器。它会将编译后的版本保留在磁盘上供以后使用。 更激进的替代方案是[提前编译](pycc.html#pycc)。 ## 1.16.3。 GPU 编程 ### 1.16.3.1。如何解决`CUDA intialized before forking`错误? 在 Linux 上,Python 标准库中的`multiprocessing`模块默认使用`fork`方法创建新进程。由于在父进程和子进程之间分配重复状态的进程,如果 CUDA 运行时在之前被初始化到 fork,CUDA 将无法在子进程中正常工作。 Numba 检测到这一点并使用`CUDA initialized before forking`消息引发`CudaDriverError`。 避免此错误的一种方法是在子进程内或创建进程池后对`numba.cuda`函数进行所有调用。但是,这并不总是可行,因为您可能希望在启动进程池之前查询可用 GPU 的数量。在 Python 3 中,您可以更改进程启动方法,如[多处理文档](https://docs.python.org/3.6/library/multiprocessing.html#contexts-and-start-methods)中所述。从`fork`切换到`spawn`或`forkserver`将避免 CUDA 初始化问题,尽管子进程不会从其父进程继承任何全局变量。 ## 1.16.4。与其他工具集成 ### 1.16.4.1。我可以“冻结”使用 Numba 的应用程序吗? 如果您使用 PyInstaller 或类似的实用程序来冻结应用程序,则可能会遇到 llvmlite 的问题。 llvmlite 需要一个非 Python DLL 才能正常工作,但冻结实用程序不会自动检测到它。您必须通知冻结实用程序 DLL 的位置:它通常会被命名为`llvmlite/binding/libllvmlite.so`或`llvmlite/binding/llvmlite.dll`,具体取决于您的系统。 ### 1.16.4.2。在 Spyder 下运行两次脚本时出错 当您在 Spyder 下的控制台中运行脚本时,Spyder 会首先尝试重新加载现有模块。这对 Numba 不起作用,并且可能产生`TypeError: No matching definition for argument type(s)`之类的错误。 Spyder 首选项中有一个修复程序。打开“首选项”窗口,选择“控制台”,然后选择“高级设置”,单击“设置 UMR 排除模块”按钮,并在弹出的文本框内添加`numba`。 要查看设置是否生效,请确保重新启动 IPython 控制台或内核。 ### 1.16.4.3。为什么 Numba 抱怨当前的语言环境? 如果收到如下错误消息: ```py RuntimeError: Failed at nopython (nopython mode backend) LLVM will produce incorrect floating-point code in the current locale ``` 这意味着您遇到了 LLVM 错误,导致浮点常量处理不正确。已知某些第三方库(如 Qt 后端到 matplotlib)会发生这种情况。 要解决此问题,您需要将语言环境强制恢复为其默认值,例如: ```py import locale locale.setlocale(locale.LC_NUMERIC, 'C') ``` ## 1.16.5。杂项 ### 1.16.5.1。如何在其他工作中引用/引用/确认 Numba? 对于学术用途,最好的选择是引用我们的 ACM 程序: [Numba:基于 LLVM 的 Python JIT 编译器。](http://dl.acm.org/citation.cfm?id=2833162&dl=ACM&coll=DL)