# 2.2。即時編譯
> 原文: [http://numba.pydata.org/numba-doc/latest/reference/jit-compilation.html](http://numba.pydata.org/numba-doc/latest/reference/jit-compilation.html)
## 2.2.1。 JIT 函數
```py
@numba.jit(signature=None, nopython=False, nogil=False, cache=False, forceobj=False, parallel=False, error_model='python', fastmath=False, locals={})
```
即時編譯修飾函數以生成高效的機器代碼。所有參數都是可選的。
如果存在,_ 簽名 _ 是單個簽名或表示函數參數和返回值的預期[類型和簽名](types.html#numba-types)的簽名列表。每個簽名可以以多種形式給出:
* [類型和簽名](types.html#numba-types)參數(例如`(numba.int32, numba.double)`)的元組,表示函數參數的類型;然后,Numba 將從參數中推斷出適當的返回類型。
* 使用[類型和簽名](types.html#numba-types)的呼叫簽名,指定返回類型和參數類型。這可以以直觀的形式給出(例如`numba.void(numba.int32, numba.double)`)。
* 上述之一的字符串表示,例如`"void(int32, double)"`。假定在`numba.types`模塊中定義字符串中使用的所有類型名稱。
_nopython_ 和 _nogil_ 是布爾標志。 _locals_ 是局部變量名稱到[類型和簽名](types.html#numba-types)的映射。
這個裝飾器有幾種操作模式:
* 如果在 _ 簽名 _ 中給出一個或多個簽名,則為它們中的每一個編譯專門化。然后調用修飾函數將嘗試選擇最佳匹配簽名,如果函數參數沒有適當的轉換,則引發 [`TypeError`](https://docs.python.org/3/library/exceptions.html#TypeError "(in Python v3.7)") 。如果轉換成功,則使用轉換的參數執行編譯的機器代碼,并根據簽名轉換返回值。
* 如果沒有給出 _ 簽名 _,則修飾函數實現延遲編譯。每次對裝飾函數的調用都會嘗試重用現有的特化(如果存在)(例如,帶有兩個整數參數的調用可能會重用參數類型`(numba.int64, numba.int64)`的特化)。如果不存在合適的特化,則會即時編譯新的特化,存儲以供以后使用,并使用轉換的參數執行。
如果為 true, _nopython_ 強制在 [nopython 模式](../glossary.html#term-nopython-mode)中編譯該函數。如果不可能,編譯將引發錯誤。
如果為真, _forceobj_ 強制在[對象模式](../glossary.html#term-object-mode)中編譯該函數。由于對象模式比 nopython 模式慢,因此這對于測試目的非常有用。
如果為 true, _nogil_ 會嘗試在編譯函數內釋放[全局解釋器鎖](https://docs.python.org/3/glossary.html#term-global-interpreter-lock "(in Python v3.7)")。只有當 Numba 能夠在 [nopython 模式](../glossary.html#term-nopython-mode)中編譯函數時才會釋放 GIL,否則將打印編譯警告。
如果為 true,則 _cache_ 允許基于文件的緩存在前一次調用中編譯該函數時縮短編譯時間。緩存保存在包含源文件的目錄的`__pycache__`子目錄中;但是,如果不允許當前用戶寫入它,則它會回退到特定于平臺的用戶范圍的緩存目錄(例如 Unix 平臺上的`$HOME/.cache/numba`)。
如果為真,則 _parallel_ 啟用多個常見 Numpy 構造的自動并行化以及相鄰并行操作的融合,以最大化緩存局部性。
_error_model_ 選項控制被零除的行為。將它設置為'python'會導致被零除以引發像 CPython 這樣的異常。將其設置為'numpy'會導致被零除以將結果設置為 _+/- inf_ 或 _nan_ 。
并非所有函數都可以緩存,因為某些功能無法始終保留到磁盤。當無法緩存函數時,會發出警告;使用 [`NUMBA_WARNINGS`](envvars.html#envvar-NUMBA_WARNINGS) 查看。
如果為真, _fastmath_ 允許使用 [LLVM 文檔](https://llvm.org/docs/LangRef.html#fast-math-flags)中描述的其他不安全的浮點變換。此外,如果[英特爾 SVML](../user/performance-tips.html#intel-svml) 的安裝速度更快,但使用的數學內在函數的版本不太準確(`4 ULP`內的答案)。
_locals_ 字典可用于強制特定局部變量的[類型和簽名](types.html#numba-types),例如,如果您想在某個時刻強制使用單精度浮點數。通常,我們建議您讓 Numba 的編譯器自己推斷局部變量的類型。
以下是兩個簽名的示例:
```py
@jit(["int32(int32)", "float32(float32)"], nopython=True)
def f(x): ...
```
在裝飾器之后沒有放任何括號等同于在沒有任何參數的情況下調用裝飾器,即:
```py
@jit
def f(x): ...
```
相當于:
```py
@jit()
def f(x): ...
```
裝飾器返回 [`Dispatcher`](#Dispatcher "Dispatcher") 對象。
注意
如果沒有給出 _ 簽名 _,則在實際編譯發生時,即首次使用某些給定的參數類型調用函數時,將引發編譯錯誤。
注意
編譯可能受某些專用[環境變量](envvars.html#numba-envvars)的影響。
## 2.2.2。生成的 JIT 函數
```py
@numba.generated_jit(nopython=False, nogil=False, cache=False, forceobj=False, locals={})
```
像 [`jit()`](#numba.jit "numba.jit") 裝飾器一樣,但是在編譯時調用裝飾函數,傳遞函數參數的 _ 類型 _。修飾函數必須返回一個可調用函數,該函數將被編譯為函數對這些類型的實現,允許靈活的專業化類型。
[`generated_jit()`](#numba.generated_jit "numba.generated_jit") 裝飾器返回 [`Dispatcher`](#Dispatcher "Dispatcher") 對象。
## 2.2.3。調度程序對象
```py
class Dispatcher
```
通過調用 [`jit()`](#numba.jit "numba.jit") 或 [`generated_jit()`](#numba.generated_jit "numba.generated_jit") 創建的對象類。您不應該嘗試以任何其他方式創建此類對象。調用 Dispatcher 對象會為調用它的參數調用已編譯的特化,使其充當已編譯的 Python 函數的加速替換。
此外,Dispatcher 對象具有以下方法和屬性:
```py
py_func
```
編譯的純 Python 函數。
```py
inspect_types(file=None, pretty=False)
```
打印出與相應的 Numba IR 一起逐行注釋的函數源代碼列表,以及各種變量的推斷類型。如果指定了 _ 文件 _,則對該文件對象進行打印,否則對 sys.stdout 進行打印。如果 _ 漂亮 _ 設置為 True,那么將在終端和筆記本中的 HTML 中生成彩色 ANSI。
也可以看看
[Numba 架構](../developer/architecture.html#architecture)
```py
inspect_llvm(signature=None)
```
返回將編譯的函數簽名鍵入到為函數生成的人類可讀 LLVM IR 的字典。如果指定了簽名關鍵字,則返回與該單個簽名對應的字符串。
```py
inspect_asm(signature=None)
```
返回將編譯的函數簽名鍵入到該函數的人類可讀的本機匯編程序代碼的字典。如果指定了簽名關鍵字,則返回與該單個簽名對應的字符串。
```py
inspect_cfg(signature=None, show_wrapped)
```
返回將編譯的函數簽名鍵入到函數的控制流圖形對象的字典。如果指定了簽名關鍵字,則返回與該單個簽名對應的字符串。
可以對控制流圖形對象進行字符串化(`str`或`repr`)以獲得 DOT 格式的圖形的文本表示。或者,使用其`.display(filename=None, view=False)`方法繪制圖形。可以將 _ 文件名 _ 選項設置為要寫入的呈現輸出的特定路徑。如果 _ 視圖 _ 選項為 True,則圖形格式(PDF)的系統默認應用程序將打開該圖。在 IPython 筆記本中,返回的對象可以是內聯圖。
用法:
```py
@jit
def foo():
...
# opens the CFG in system default application
foo.inspect_cfg(foo.signatures[0]).display(view=True)
```
```py
recompile()
```
重新編譯所有現有簽名。這可能很有用,例如,如果函數凍結了全局變量或閉包變量,并且 Python 中的值已更改。由于編譯并不便宜,因此主要用于測試和交互式使用。
```py
parallel_diagnostics(signature=None, level=1)
```
打印給定簽名的并行診斷信息。如果沒有簽名,則打印所有已知簽名。 `level`用于調整詳細程度,`level=1`(默認值)是最小詳細程度,2,3 和 4 級提供更高級別的詳細程度。
```py
get_metadata(signature=None)
```
獲取給定簽名的編譯元數據。這對于 Numba 和 Numba 擴展的開發人員非常有用。
## 2.2.4。矢量化函數(ufuncs 和 DUFuncs)
```py
@numba.vectorize(*, signatures=[], identity=None, nopython=True, target='cpu', forceobj=False, cache=False, locals={})
```
編譯裝飾函數并將其包裝為 [Numpy ufunc](http://docs.scipy.org/doc/numpy/reference/ufuncs.html) 或 Numba [`DUFunc`](#numba.DUFunc "numba.DUFunc") 。可選的 _nopython_ , _forceobj_ 和 _locals_ 參數具有與 [`numba.jit()`](#numba.jit "numba.jit") 相同的含義。
_ 簽名 _ 是一個可選的簽名列表,以與 [`numba.jit()`](#numba.jit "numba.jit") _ 簽名 _ 參數相同的形式表示。如果 _ 簽名 _ 非空,那么裝飾器會將用戶 Python 函數編譯為 Numpy ufunc。如果沒有給出 _ 簽名 _,那么裝飾器會將用戶 Python 函數包裝在 [`DUFunc`](#numba.DUFunc "numba.DUFunc") 實例中,只要 Numpy 找不到匹配項,它就會在調用時編譯用戶函數循環輸入參數。如果 _ 目標 _ 是`"parallel"`,則需要 _ 簽名 _。
_ 標識 _ 是正在實現的函數的標識(或單位)值。可能的值為 0,1,None 和字符串`"reorderable"`。默認值為 None。 None 和`"reorderable"`均表示該函數沒有標識值; `"reorderable"`另外指定沿多個軸的減少可以重新排序。
如果有多個 _ 簽名 _,則必須從更具體到最不具體的順序進行排序。否則,Numpy 基于類型的調度可能無法按預期工作。例如,以下是錯誤的:
```py
@vectorize(["float64(float64)", "float32(float32)"])
def f(x): ...
```
因為在單精度數組上運行它將選擇編譯函數的`float64`版本,導致執行效率低得多。正確的調用是:
```py
@vectorize(["float32(float32)", "float64(float64)"])
def f(x): ...
```
_target_ 是后端目標的字符串;可用值為“cpu”,“parallel”和“cuda”。要使用多線程版本,請將目標更改為“parallel”(這需要指定簽名):
```py
@vectorize(["float64(float64)", "float32(float32)"], target='parallel')
def f(x): ...
```
對于 CUDA 目標,請使用“cuda”:
```py
@vectorize(["float64(float64)", "float32(float32)"], target='cuda')
def f(x): ...
```
可以緩存已編譯的函數以減少將來的編譯時間。通過將 _ 緩存 _ 設置為 True 來啟用它。只有“cpu”和“parallel”目標支持緩存。
```py
@numba.guvectorize(signatures, layout, *, identity=None, nopython=True, target='cpu', forceobj=False, cache=False, locals={})
```
[`numba.vectorize()`](#numba.vectorize "numba.vectorize") 的廣義版本。雖然 [`numba.vectorize()`](#numba.vectorize "numba.vectorize") 將產生一個簡單的 ufunc,其核心功能(你正在裝飾的功能)在標量操作數上運行并返回一個標量值, [`numba.guvectorize()`](#numba.guvectorize "numba.guvectorize") 允許你創建一個 [Numpy ufunc](http://docs.scipy.org/doc/numpy/reference/ufuncs.html) ,其核心功能采用各種維度的數組參數。
附加參數 _layout_ 是一個字符串,以符號形式指定參數類型和返回類型的維度和大小關系。例如,矩陣乘法的布局字符串為`"(m,n),(n,p)->(m,p)"`。它的定義可能是(函數體省略):
```py
@guvectorize(["void(float64[:,:], float64[:,:], float64[:,:])"],
"(m,n),(n,p)->(m,p)")
def f(a, b, result):
"""Fill-in *result* matrix such as result := a * b"""
...
```
如果其中一個參數應該是標量,則相應的布局規范是`()`,并且該參數將真正作為零維數組給出(您必須取消引用它才能獲得標量值)。例如,具有可參數窗口寬度的[一維移動平均值](../user/examples.html#example-movemean)可以具有`"(n),()->(n)"`的布局串。
請注意,任何輸出都將作為附加函數參數預先分配給您:您的代碼必須使用您正在實現的函數的適當值填充它。
如果您的函數沒有輸出數組,則應省略布局字符串中的“箭頭”(例如`"(n),(n)"`)。
也可以看看
Numpy 支持的[布局字符串](http://docs.scipy.org/doc/numpy/reference/c-api.generalized-ufuncs.html#details-of-signature)的規范。請注意,Numpy 使用術語“簽名”,我們不幸地將其用于其他內容。
可以緩存已編譯的函數以減少將來的編譯時間。通過將 _ 緩存 _ 設置為 True 來啟用它。只有“cpu”和“parallel”目標支持緩存。
```py
class numba.DUFunc
```
通過調用沒有簽名的 [`numba.vectorize()`](#numba.vectorize "numba.vectorize") 創建的對象類。
DUFunc 實例應該與 Numpy `ufunc`對象的行為類似,但有一個重要區別:調用時循環生成。當調用 ufunc 時,Numpy 會查看為該 ufunc 注冊的現有循環,并且如果找不到一個無法安全地投射輸入以適應的循環,則會引發`TypeError`。當呼叫 DUFunc 時,Numba 將呼叫委托給 Numpy。如果 Numpy ufunc 調用失敗,那么 Numba 會嘗試為給定的輸入類型構建一個新循環,并再次調用 ufunc。如果第二次調用嘗試失敗或發生編譯錯誤,則 DUFunc 將異常傳遞給調用者。
也可以看看
用戶指南中的“[動態通用函數](../user/vectorize.html#dynamic-universal-functions)”部分演示了 [`DUFunc`](#numba.DUFunc "numba.DUFunc") 的調用時間行為,并討論了調用順序對 Numba 如何生成基礎`ufunc`的影響。
```py
ufunc
```
實際的 Numpy `ufunc`對象由 [`DUFunc`](#numba.DUFunc "numba.DUFunc") 實例構建。請注意, [`DUFunc`](#numba.DUFunc "numba.DUFunc") 對象維護了正確的 ufunc 功能所需的幾個重要數據結構(特別是動態編譯的循環)。用戶不應傳遞`ufunc`值而不確保底層 [`DUFunc`](#numba.DUFunc "numba.DUFunc") 不會被垃圾收集。
```py
nin
```
DUFunc(ufunc)輸入的數量。見 [ufunc.nin](http://docs.scipy.org/doc/numpy/reference/generated/numpy.ufunc.nin.html#numpy.ufunc.nin) 。
```py
nout
```
DUFunc 輸出的數量。見 [ufunc.nout](http://docs.scipy.org/doc/numpy/reference/generated/numpy.ufunc.nout.html#numpy.ufunc.nout) 。
```py
nargs
```
可能的 DUFunc 參數總數(應為 [`nin`](#numba.DUFunc.nin "numba.DUFunc.nin") + [`nout`](#numba.DUFunc.nout "numba.DUFunc.nout") )。見 [ufunc.nargs](http://docs.scipy.org/doc/numpy/reference/generated/numpy.ufunc.nargs.html#numpy.ufunc.nargs) 。
```py
ntypes
```
DUFunc 支持的輸入類型數。見 [ufunc.ntypes](http://docs.scipy.org/doc/numpy/reference/generated/numpy.ufunc.ntypes.html#numpy.ufunc.ntypes) 。
```py
types
```
以字符串形式提供的受支持類型的列表。見 [ufunc.types](http://docs.scipy.org/doc/numpy/reference/generated/numpy.ufunc.types.html#numpy.ufunc.types) 。
```py
identity
```
使用 ufunc 作為縮減時的標識值。見 [ufunc.identity](http://docs.scipy.org/doc/numpy/reference/generated/numpy.ufunc.identity.html#numpy.ufunc.identity) 。
```py
reduce(A, *, axis, dtype, out, keepdims)
```
通過沿一個軸應用 DUFunc,將 _A_ 的尺寸減一。見 [ufunc.reduce](http://docs.scipy.org/doc/numpy/reference/generated/numpy.ufunc.reduce.html#numpy.ufunc.reduce) 。
```py
accumulate(A, *, axis, dtype, out)
```
累積將運算符應用于所有元素的結果。見 [ufunc.accumulate](http://docs.scipy.org/doc/numpy/reference/generated/numpy.ufunc.accumulate.html#numpy.ufunc.accumulate) 。
```py
reduceat(A, indices, *, axis, dtype, out)
```
在單個軸上使用指定切片執行(局部)縮減。見 [ufunc.reduceat](http://docs.scipy.org/doc/numpy/reference/generated/numpy.ufunc.reduceat.html#numpy.ufunc.reduceat) 。
```py
outer(A, B)
```
將 ufunc 應用于所有對( _a_ , _b_ )與 _a_ 在 _A_ 和 _b_ 中 _B_ 。見 [ufunc.outer](http://docs.scipy.org/doc/numpy/reference/generated/numpy.ufunc.outer.html#numpy.ufunc.outer) 。
```py
at(A, indices, *, B)
```
對 _ 索引 _ 指定的元素在操作數 _A_ 上執行無緩沖就位操作。如果您使用的是 Numpy 1.7 或更早版本,則此方法將不存在。見 [ufunc.at](http://docs.scipy.org/doc/numpy/reference/generated/numpy.ufunc.at.html#numpy.ufunc.at) 。
注意
在極少數情況下,矢量化函數可能會顯示[意外警告或錯誤](fpsemantics.html#ufunc-fpu-errors)。
## 2.2.5。 C 回調
```py
@numba.cfunc(signature, nopython=False, cache=False, locals={})
```
即時編譯修飾函數以生成高效的機器代碼。編譯后的代碼包含在一個瘦 C 回調中,使得它可以使用自然的 C ABI 進行調用。
_ 簽名 _ 是表示 C 回調簽名的單個簽名。它必須與 [`jit()`](#numba.jit "numba.jit") 中的形式相同。裝飾器不會檢查簽名中的類型是否在 C 中具有明確定義的表示。
_nopython_ 和 _ 緩存 _ 是布爾標志。 _locals_ 是局部變量名稱到[類型和簽名](types.html#numba-types)的映射。它們都與 [`jit()`](#numba.jit "numba.jit") 中的含義相同。
裝飾器返回 [`CFunc`](#CFunc "CFunc") 對象。
注意
C 回調目前不支持[對象模式](../glossary.html#term-object-mode)。
```py
class CFunc
```
由 [`cfunc()`](#numba.cfunc "numba.cfunc") 創建的對象類。 [`CFunc`](#CFunc "CFunc") 對象公開以下屬性和方法:
```py
address
```
已編譯的 C 回調的地址,為整數。
```py
cffi
```
一個 [cffi](https://cffi.readthedocs.org/) 函數指針實例,作為參數傳遞給 [cffi](https://cffi.readthedocs.org/) - 包裝函數。指針的類型是`void *`,因此只有在將其傳遞給 [cffi](https://cffi.readthedocs.org/) 時才會進行最小類型檢查。
```py
ctypes
```
一個 [`ctypes`](https://docs.python.org/3/library/ctypes.html#module-ctypes "(in Python v3.7)") 回調實例,好像它是使用 [`ctypes.CFUNCTYPE()`](https://docs.python.org/3/library/ctypes.html#ctypes.CFUNCTYPE "(in Python v3.7)") 創建的。
```py
native_name
```
已編譯的 C 回調的名稱。
```py
inspect_llvm()
```
返回為 C 回調生成的人類可讀的 LLVM IR。 [`native_name`](#CFunc.native_name "CFunc.native_name") 是在 IR 中定義此回調的名稱。
- 1. 用戶手冊
- 1.1。 Numba 的約 5 分鐘指南
- 1.2。概述
- 1.3。安裝
- 1.4。使用@jit 編譯 Python 代碼
- 1.5。使用@generated_jit 進行靈活的專業化
- 1.6。創建 Numpy 通用函數
- 1.7。用@jitclass 編譯 python 類
- 1.8。使用@cfunc 創建 C 回調
- 1.9。提前編譯代碼
- 1.10。使用@jit 自動并行化
- 1.11。使用@stencil裝飾器
- 1.12。從 JIT 代碼 中回調到 Python 解釋器
- 1.13。性能提示
- 1.14。線程層
- 1.15。故障排除和提示
- 1.16。常見問題
- 1.17。示例
- 1.18。會談和教程
- 2. 參考手冊
- 2.1。類型和簽名
- 2.2。即時編譯
- 2.3。提前編譯
- 2.4。公用事業
- 2.5。環境變量
- 2.6。支持的 Python 功能
- 2.7。支持的 NumPy 功能
- 2.8。與 Python 語義的偏差
- 2.9。浮點陷阱
- 2.10。 Python 2.7 壽命終止計劃
- 3. 用于 CUDA GPU 的 Numba
- 3.1。概述
- 3.2。編寫 CUDA 內核
- 3.3。內存管理
- 3.4。編寫設備功能
- 3.5。 CUDA Python 中支持的 Python 功能
- 3.6。支持的原子操作
- 3.7。隨機數生成
- 3.8。設備管理
- 3.10。示例
- 3.11。使用 CUDA 模擬器 調試 CUDA Python
- 3.12。 GPU 減少
- 3.13。 CUDA Ufuncs 和廣義 Ufuncs
- 3.14。共享 CUDA 內存
- 3.15。 CUDA 陣列接口
- 3.16。 CUDA 常見問題
- 4. CUDA Python 參考
- 4.1。 CUDA 主機 API
- 4.2。 CUDA 內核 API
- 4.3。內存管理
- 5. 用于 AMD ROC GPU 的 Numba
- 5.1。概述
- 5.2。編寫 HSA 內核
- 5.3。內存管理
- 5.4。編寫設備功能
- 5.5。支持的原子操作
- 5.6。代理商
- 5.7。 ROC Ufuncs 和廣義 Ufuncs
- 5.8。示例
- 6. 擴展 Numba
- 6.1。高級擴展 API
- 6.2。低級擴展 API
- 6.3。示例:間隔類型
- 7. 開發者手冊
- 7.1。貢獻給 Numba
- 7.2。 Numba 建筑
- 7.3。多態調度
- 7.4。關于發電機的注意事項
- 7.5。關于 Numba Runtime 的注意事項
- 7.6。使用 Numba Rewrite Pass 獲得樂趣和優化
- 7.7。實時變量分析
- 7.8。上市
- 7.9。模板注釋
- 7.10。關于自定義管道的注意事項
- 7.11。環境對象
- 7.12。哈希 的注意事項
- 7.13。 Numba 項目路線圖
- 8. Numba 增強建議
- 9. 術語表