# 1.1. Numba 的 ~ 5 分鐘指南
> 原文: [http://numba.pydata.org/numba-doc/latest/user/5minguide.html](http://numba.pydata.org/numba-doc/latest/user/5minguide.html)
Numba 是 Python 的即時(JIT)編譯器,它最適用于使用 NumPy 數組、函數和循環的代碼。使用 Numba 的最常用方法是使用其裝飾器集合,通過作用于您的函數來指示 Numba 編譯它們。當調用 Numba 修飾函數時,它被編譯為機器代碼“即時”(JIT)執行,從而使您的全部或部分代碼隨后可以以本機機器代碼速度運行!
Numba 可直接運行于下列環境:
* 操作系統:Windows(32 位和 64 位),OSX 和 Linux(32 位和 64 位)
* 架構:x86,x86_64,ppc64le。在 armv7l,armv8l(aarch64)上進行實驗。
* GPU:Nvidia CUDA。 在 AMD ROC 上的應用是實驗性質的。
* CPython
* NumPy 1.10 - 最新的
## 1.1.1. 如何獲取Numba?
Numba 是 [Anaconda Python 發行版](https://www.anaconda.com/)的一個 [conda](https://conda.io/docs/) 軟件包:
```py
$ conda install numba
```
Numba 還有wheels(.whl)可供選擇:
```py
$ pip install numba
```
Numba 也可以從[源碼](installing.html#numba-source-install-instructions) (校對注:md超鏈接需要整體修改) 編譯,但我們不建議首次使用 Numba 的用戶使用這種方法。
Numba 通常用作核心包,因此其依賴性被盡可能減小,但可以額外安裝下列包以提供附加功能:
* `scipy` - 支持編譯 `numpy.linalg` 的函數。
* `colorama` - 支持回溯/錯誤消息中的顏色突出顯示。
* `pyyaml` - 啟用 Numba 配置的 YAML 配置文件。
* `icc_rt` - 允許使用 Intel SVML(高性能短矢量數學庫,僅限 x86_64 架構)。安裝說明在[性能提示](performance-tips.html#intel-svml) (校對注:md超鏈接需要整體修改) 中。
## 1.1.2. Numba 會對我的代碼有用嗎?
這取決于你的代碼是什么樣的,如果你的代碼是以數字為導向的(做很多數學運算),使用 NumPy 和/或有很多循環,那么 Numba 通常是一個不錯的選擇。在以下的例子中,我們將應用最基本的 Numba 的 JIT 裝飾器`@jit`來嘗試加速某些函數,以展示哪些函數會被改善,哪些函數不能被改善。
Numba 可以改善的代碼看起來像這樣:
```py
from numba import jit
import numpy as np
x = np.arange(100).reshape(10, 10)
@jit(nopython=True) # 使用 "nopython" 模式以提供更好的性能, 等價于 @njit
def go_fast(a): # 當函數第一次被調用時會被編譯為機器碼
trace = 0
for i in range(a.shape[0]): # Numba 偏好循環
trace += np.tanh(a[i, i]) # Numba 偏好 NumPy 函數
return a + trace # Numba 偏好 NumPy 廣播(broadcasting)
print(go_fast(x))
```
對于這樣的代碼(如果有的話)Numba將無法很好地工作:
```py
from numba import jit
import pandas as pd
x = {'a': [1, 2, 3], 'b': [20, 30, 40]}
@jit
def use_pandas(a): # 這個函數無法受益于 Numba jit
df = pd.DataFrame.from_dict(a) # Numba 不識別 pd.DataFrame
df += 1 # Numba 不明白這是什么
return df.cov() # 或是這個
print(use_pandas(x))
```
請注意,Numba 不識別 Pandas,因此 Numba 只是通過解釋器運行此代碼,卻增加了 Numba 內部開銷的成本!
## 1.1.3. 什么是`nopython`模式?
Numba `@jit`裝飾器基本上以兩種編譯模式運行,`nopython`模式和`object`模式。在上面的`go_fast`示例中,在`@jit`裝飾器中設置了`nopython=True`,這是指示 Numba 在`nopython`模式下運行。 `nopython`編譯模式的行為本質上是編譯裝飾函數,以便它完全運行而不需要 Python 解釋器的參與。這是使用 Numba `jit`裝飾器的推薦和最佳實踐方式,因為它可以獲得最佳性能。
如果`nopython`模式下的編譯失敗,Numba 可以使用`object mode`進行編譯,如果未設置`nopython=True`,這是`@jit`裝飾器的降級模式(如上面的`use_pandas`示例所示)。在這種模式下,Numba 將識別它可以編譯的循環,并將它們編譯成在機器代碼中運行的函數,并且它將運行解釋器中的其余代碼。為獲得最佳性能,請避免使用此模式!
## 1.1.4. 如何衡量 Numba 的表現?
首先,回想一下 Numba 必須在執行函數的機器代碼版本之前對于你的包含特定參數的函數進行編譯,這需要時間。但是,一旦編譯完成,Numba 會為所特定類型的參數緩存函數的機器代碼版本。如果再次使用相同類型調用它,它可以重用緩存版本而不必再次編譯。
測量性能時,一個非常常見的錯誤是不考慮上述行為,并使用一個簡單的計時器對時間進行一次編碼,而該計時器包括在執行時編譯函數所需的時間。
例如:
```py
from numba import jit
import numpy as np
import time
x = np.arange(100).reshape(10, 10)
@jit(nopython=True)
def go_fast(a): # Function is compiled and runs in machine code
trace = 0
for i in range(a.shape[0]):
trace += np.tanh(a[i, i])
return a + trace
# DO NOT REPORT THIS... COMPILATION TIME IS INCLUDED IN THE EXECUTION TIME!
start = time.time()
go_fast(x)
end = time.time()
print("Elapsed (with compilation) = %s" % (end - start))
# NOW THE FUNCTION IS COMPILED, RE-TIME IT EXECUTING FROM CACHE
start = time.time()
go_fast(x)
end = time.time()
print("Elapsed (after compilation) = %s" % (end - start))
```
如此會打印(舉例):
```py
Elapsed (with compilation) = 0.33030009269714355
Elapsed (after compilation) = 6.67572021484375e-06
```
衡量 Numba JIT 對您的代碼的影響的一個好方法是使用 [timeit](https://docs.python.org/3/library/timeit.html) 模塊函數來執行時間,這些函數測量多次執行迭代,因此可以適應編譯時間在第一次執行。
另外,如果編譯時間是一個問題,Numba JIT 支持已編譯函數的[磁盤緩存](../reference/jit-compilation.html#jit-decorator-cache) (校對注:md超鏈接需要整體修改) ,并且還具有 [Ahead-Of-Time](../reference/aot-compilation.html#aot-compilation) (校對注:md超鏈接需要整體修改) 編譯模式。
## 1.1.5. Numba有多快?
假設 Numba 可以在`nopython`模式下運行,或者至少編譯一些循環,它將針對您的特定 CPU 進行編譯。加速因應用而異,但可以是一到兩個數量級。 Numba 有一個[性能指南](performance-tips.html#performance-tips) (校對注:md超鏈接需要整體修改) ,涵蓋了獲得額外性能的常用選項。
## 1.1.6. Numba 如何工作?
Numba 讀取被裝飾函數的 Python 字節碼,并將其與有關函數輸入參數類型的信息相結合。Numba會分析并優化您的代碼,最后使用 LLVM 編譯器庫生成函數的機器代碼版本,這將針對您的 CPU 功能量身定制。此后每次調用函數時都會使用此編譯版本。
## 1.1.7. 其他有意義的東西:
Numba 有很多裝飾器,我們見過`@jit`,但也有:
* `@njit` - 這是`@jit(nopython=True)`的別名,因為它非常常用!
* `@vectorize` - 產生 NumPy `ufunc`(支持所有`ufunc`方法)。 [文件在這里](vectorize.html#vectorize) (校對注:md超鏈接需要整體修改) 。
* `@guvectorize` - 產生 NumPy 廣義`ufunc`。 [文件在這里](vectorize.html#guvectorize) (校對注:md超鏈接需要整體修改) 。
* `@stencil` - 將函數聲明為類似模板操作的內核。 [文件在這里](stencil.html#numba-stencil) (校對注:md超鏈接需要整體修改) 。
* `@jitclass` - 用于 jit 感知類。 [文件在這里](jitclass.html#jitclass) (校對注:md超鏈接需要整體修改) 。
* `@cfunc` - 聲明一個用作本機回調的函數(從 C / C ++等調用)。 [文件在這里](cfunc.html#cfunc) (校對注:md超鏈接需要整體修改) 。
* `@overload` - 注冊您自己的函數實現,以便在 nopython 模式下使用,例如: `@overload(scipy.special.j0)`。 [文件在這里](../extending/high-level.html#high-level-extending) (校對注:md超鏈接需要整體修改) 。
一些裝飾器提供額外選項:
* `parallel = True` - [開啟](../reference/jit-compilation.html#jit-decorator-parallel)(校對注:md超鏈接需要整體修改)函數的[自動并行化](parallel.html#numba-parallel)(校對注:md超鏈接需要整體修改)。
* `fastmath = True` - 為該函數啟用 [fast-math](../reference/jit-compilation.html#jit-decorator-fastmath) (校對注:md超鏈接需要整體修改) 表現。
ctypes / cffi / cython 互用性:
* `cffi` - `nopython`模式支持調用 [CFFI](../reference/pysupported.html#cffi-support) (校對注:md超鏈接需要整體修改)功能。
* `ctypes` - `nopython`模式支持調用 [ctypes](../reference/pysupported.html#ctypes-support) (校對注:md超鏈接需要整體修改) 包裝函數。
* Cython 導出函數[可調用](../extending/high-level.html#cython-support)(校對注:md超鏈接需要整體修改)。
### 1.1.7.1. 用于 GPU 目的:
Numba 可以面向 [Nvidia CUDA](https://developer.nvidia.com/cuda-zone) 和 [AMD ROC](https://rocm.github.io/)(實驗性的) GPU 進行程序設計。您可以用純 Python 編寫內核,讓 Numba 處理計算和數據移動(或顯式執行此操作)。參見 [CUDA](../cuda/index.html#cuda-index)(校對注:md超鏈接需要整體修改) 或 [ROC](../roc/index.html#roc-index) (校對注:md超鏈接需要整體修改) 的 Numba 文檔。
- 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. 術語表