Numba:用CUDA加速的高性能Python編譯器

2021-01-07 IT168

  【IT168 編譯】Python是一種高效的動態程式語言,廣泛應用於科學、工程和數據分析應用領域。使python如此受歡迎的因素有很多,包括其乾淨的、表達性的語法和標準的數據結構,綜合的「內置電池」標準庫,優秀的文檔,庫和工具的廣泛生態系統,專業支持的可用性,以及大而開放的社區。不過,也許最重要的原因是,像Python這樣的動態類型化的解釋語言能夠提高生產率。Python足夠敏捷與靈活,使它成為快速原型開發的一種偉大語言,同時也是構建完整系統的語言。

  但是Python的最大優點也可能是它最大的缺點:它的靈活性和無類型的高級語法會導致數據和計算密集型程序的性能不佳。出於這個原因,關心效率的Python程式設計師經常在C中重寫他們的最內層的循環,並從Python調用編譯的C函數。有許多項目旨在簡化這種優化,例如Cython,但這往往需要學習一種新的語法。理想情況下,Python程式設計師希望在不使用另一種程式語言的情況下使其現有的Python代碼更快,當然,許多人也希望使用加速器來獲得更高的性能。

  Numba:高性能計算的高生產率

  在這篇文章中,筆者將向你介紹一個來自Anaconda的Python編譯器Numba,它可以在CUDA-capable GPU或多核cpu上編譯Python代碼。Python通常不是一種編譯語言,你可能想知道為什麼要使用Python編譯器。答案當然是:運行本地編譯的代碼要比運行動態的、解譯的代碼快很多倍。Numba允許你為Python函數指定類型籤名,從而在運行時啟用編譯(這就是「Just-in-Time」,即時,也可以說JIT編譯)。Numba動態編譯代碼的能力意味著你不會因此而拋棄Python的靈活性。這是向提供高生產率編程和高性能計算的完美結合邁出的一大步。

  使用Numba可以編寫標準的Python函數,並在CUDA-capable GPU上運行它們。Numba是為面向數組的計算任務而設計的,很像大家常用的NumPy庫。在面向數組的計算任務中,數據並行性對於像GPU這樣的加速器是很自然的。Numba了解NumPy數組類型,並使用它們生成高效的編譯代碼,用於在GPU或多核CPU上執行。所需的編程工作可以很簡單,就像添加一個函數修飾器來指示Numba為GPU編譯一樣。例如,在下面的代碼中,@ vectorize decorator會生成一個編譯的、矢量化的標量函數在運行時添加的版本,這樣它就可以用於在GPU上並行處理數據數組。

  import numpy as np

  from numba import vectorize

  @vectorize(['float32(float32, float32)'], target='cuda')

  def Add(a, b):

  return a + b

  # Initialize arrays

  N = 100000

  A = np.ones(N, dtype=np.float32)

  B = np.ones(A.shape, dtype=A.dtype)

  C = np.empty_like(A, dtype=A.dtype)

  # Add arrays on GPU

  C = Add(A, B)

  要在CPU上編譯和運行相同的函數,我們只需將目標更改為「CPU」,它將在編譯水平上帶來性能,在CPU上向量化C代碼。這種靈活性可以幫助你生成更可重用的代碼,並允許你在沒有GPU的機器上開發。

  關於Python 的GPU-Accelerated庫

  CUDA並行計算平臺的優勢之一是其可用的GPU加速庫的闊度。Numba團隊的另一個項目叫做pyculib,它提供了一個Python接口,用於CUDA cuBLAS(dense linear algebra,稠密線性代數),cuFFT(Fast Fourier Transform,快速傅立葉變換),和cuRAND(random number generation,隨機數生成)庫。許多應用程式都能夠通過使用這些庫獲得顯著的加速效果,而不需要編寫任何特定於GPU的代碼。例如,下面的代碼使用「XORWOW」偽隨機數生成器在GPU上生成100萬個均勻分布的隨機數。

  import numpy as np

  from pyculib import rand as curand

  prng = curand.PRNG(rndtype=curand.PRNG.XORWOW)

  rand = np.empty(100000)

  prng.uniform(rand)

  print rand[:10]

  CUDA Python的高並行性

  Anaconda(原名Continuum Analytics)認識到,在某些計算上實現大的速度需要一個更具表現力的編程接口,它比庫和自動循環矢量化更詳細地控制並行性。因此,Numba有另一組重要的特性,構成了其非正式名稱「CUDA Python」。Numba公開了CUDA編程模型,正如CUDA C/ C++,但是使用純python語法,這樣程式設計師就可以創建自定義、調優的並行內核,而不會放棄python帶來的便捷和優勢。Numba的CUDA JIT(通過decorator或函數調用可用)在運行時編譯CUDA Python函數,專門針對你所使用的類型,它的CUDA Python API提供了對數據傳輸和CUDA流的顯式控制,以及其他特性。

  下面的代碼示例演示了一個簡單的Mandelbrot設置內核。請注意,mandel_kernel函數使用Numba提供的cuda.threadIdx,cuda.blockIdx,cuda.blockDim和cuda.gridDim架構來計算當前線程的全局X和Y像素索引。與其他CUDA語言一樣,我們通過插入在括號內一個「執行配置」(CUDA-speak用於線程數和線程塊啟動內核),在函數名和參數列表之間中: mandel_kernel[griddim, blockdim](-2.0, 1.0, -1.0, 1.0, d_image, 20)。你還可以看到使用to_host和to_device API函數來從GPU中複製數據。

  Mandelbrot的例子將在Github上持續更新。

  @cuda.jit(device=True)

  def mandel(x, y, max_iters):

  """

  Given the real and imaginary parts of a complex number,

  determine if it is a candidate for membership in the Mandelbrot

  set given a fixed number of iterations.

  """

  c = complex(x, y)

  z = 0.0j

  for i in range(max_iters):

  z = z*z + c

  if (z.real*z.real + z.imag*z.imag) >= 4:

  return i

  return max_iters

  @cuda.jit

  def mandel_kernel(min_x, max_x, min_y, max_y, image, iters):

  height = image.shape[0]

  width = image.shape[1]

  pixel_size_x = (max_x - min_x) / width

  pixel_size_y = (max_y - min_y) / height

  startX = cuda.blockDim.x * cuda.blockIdx.x + cuda.threadIdx.x

  startY = cuda.blockDim.y * cuda.blockIdx.y + cuda.threadIdx.y

  gridX = cuda.gridDim.x * cuda.blockDim.x;

  gridY = cuda.gridDim.y * cuda.blockDim.y;

  for x in range(startX, width, gridX):

  real = min_x + x * pixel_size_x

  for y in range(startY, height, gridY):

  imag = min_y + y * pixel_size_y

  image[y, x] = mandel(real, imag, iters)

  gimage = np.zeros((1024, 1536), dtype = np.uint8)

  blockdim = (32, 8)

  griddim = (32,16)

  start = timer()

  d_image = cuda.to_device(gimage)

  mandel_kernel[griddim, blockdim](-2.0, 1.0, -1.0, 1.0, d_image, 20)

  d_image.to_host()

  dt = timer() - start

  print "Mandelbrot created on GPU in %f s" % dt

  imshow(gimage)

  在一臺帶有NVIDIA Tesla P100 GPU和Intel Xeon E5-2698 v3 CPU的伺服器上,這個CUDA Python Mandelbrot代碼運行的速度比純Python版本快1700倍。1700倍似乎有些不切實際,但請記住,我們正在比較編譯的、並行的、GPU加速的Python代碼來解釋CPU上的單線程Python代碼。

  今天開始使用Numba吧

  Numba為Python開發人員提供了一種簡單的進入GPU加速計算的方法,並提供了一種使用越來越複雜的CUDA代碼的方法,其中至少有新語法和術語。你可以從簡單的函數decorator開始實現自動編譯函數,或者使用pyculib的強大的CUDA庫。當你提高對並行編程概念的理解時,當你需要對於並行線程的有表現力且靈活的控制時,CUDA可以在不需要你第一天就完全了解的情況下使用。

  Numba是一個BSD認證的開源項目,它本身嚴重依賴於LLVM編譯器的功能。Numba的GPU後端使用了基於LLVM的NVIDIA編譯器SDK。CUDA庫周圍的pyculib包裝器也是開源且經過BSD認證的。

  要開始使用Numba,第一步是下載並安裝Anaconda Python發行版,這是一個「完全免費的、用於大規模數據處理、預測分析和科學計算的Python發行版」,其中包括許多流行的軟體包(Numpy、Scipy、Matplotlib、iPython等)和「conda」,這是一個強大的包管理器。一旦您安裝了Anaconda,通過鍵入conda安裝numba cudatoolkit pyculib,安裝所需的CUDA包。然後在ContinuumIO github存儲庫中查看CUDA的Numba教程。筆者建議你在Anaconda的博客上查看Numba的帖子。

相關焦點

  • Numba:基於CUDA加速的高性能Python
    Numba:高效的高性能計算這篇文章將向您介紹基於Anaconda的Python編譯器Numba,它可以編譯Python代碼,以便在支持CUDA在GPU或多核CPU上執行。由於Python通常不是編譯語言,您可能會想知道為什麼需要Python編譯器。答案當然是運行本地已編譯代碼比運行動態解釋代碼快許多倍。
  • Python · numba 的基本應用
    雖然我用 Python 也有那麼兩年左右了,但也只能模模糊糊地感受到這麼兩點:* Python 太動態了* 如果能事先編譯一下 Python,讓它靜態一點,速度應該就會上來於是我們就有了 cython。然而 cython 畢竟不是原生的 Python 代碼,使用起來還是有諸多不便的。為此,numba 就成了一個功能強大又容易上手的替代選擇。
  • 讓Python代碼更快運行的 5 種方法
    PyPy在選擇CPython的簡易替代語言時,PyPy無疑是最佳之選(如Quora就是由它編寫而成)。由於與現有Python代碼保持高度兼容性,PyPy也是默認程序運行時的一個很好選擇。不久後,Pyston就可以被認為是遠程生產就緒語言。相關連結:https://github.com/dropbox/pystonNuitkaNuitka 是一個Python的替代品,一些團隊正用它做完全的Python編譯工具,並嘗試將Python代碼轉譯為其它可高速運行的程式語言。
  • 為了CUDA:NVIDIA收購高性能計算編譯器廠商PGI
    NVIDIA今天官方宣布,已經收購在高性能計算領域領先的編輯器和工具供應商The Portland Group (PGI)。PGI是意法半導體旗下全資子公司,創立於1989年,在高性能計算編譯器技術上擁有悠久的歷史,客戶包括Intel、IBM、Linux、OpenMP、GPGPU、ARM。
  • 都有Python 了,還要什麼編譯器!
    編譯的目的是將源碼轉化為機器可識別的可執行程序,在早期,每次編譯都需要重新構建所有東西,後來人們意識到可以讓編譯器自動完成一些工作,從而提升編譯效率。但「編譯器不過是用於代碼生成的軟機器,你可以使用你想要的任何語言來生成代碼」,真的是必要的嗎?
  • 讓 Windows 的 R 用上 CUDA
    在 Linux 和 macOS 下, CUDA 程序和 C++ 程序都使用 gcc 編譯器, 但是在 Windows 下,Rcpp 的包必須用 MinGW 編譯器, CUDA 的包必須用 MSVC 編譯器,需要一定的技巧才能讓 R 用上 CUDA。
  • 一行代碼讓你的Python運行速度提高100倍!Python真強!
    Python用的好,豬也能飛起來。今天,帶大家學習如何讓Python飛起來的方法,乾貨滿滿哦!python一直被病垢運行速度太慢,但是實際上python的執行效率並不慢,慢的是python用的解釋器Cpython運行效率太差。「一行代碼讓python的運行速度提高100倍」這絕不是譁眾取寵的論調。我們來看一下這個最簡單的例子,從1一直累加到1億。
  • 11 個優秀的 Python 編譯器和解釋器
    它帶有 C/C++ 編譯器,大多數時候不會用到。除此之外,它只有 Python 編譯器,沒有其它包。網址:https://winpython.github.io4.Skulpt網站:https://www.activestate.com/products/activepython8. Nutika
  • CUDA之CUDA編程模型概述(一)
    CUDA平臺也提供了著一些列的工具供我們使用,我們這一章主要就是講解這些工具怎麼用,如何編寫調試CUDA程序。以及編寫兩個矩陣運算有關的CUDA應用,以供大家把玩。CUDA編程模型概述CUDA編程模型為應用和硬體設備之間的橋梁,所以CUDA C是編譯型語言,不是解釋型語言,OpenCL就有點類似於解釋型語言,通過編譯器和連結,給作業系統執行(作業系統包括GPU在內的系統),下面的結構圖片能形象的表現他們之間的關係:
  • python 開發編譯器
    (點擊上方藍字,快速關注我們)來源:伯樂在線專欄作者 - 下弦月如有好文章投稿,請點擊 → 這裡了解詳情如需轉載,發送「轉載」二字查看說明引言最近剛剛用python寫完了一個解析protobuf文件的簡單編譯器,深感ply實現詞法分析和語法分析的簡潔方便。
  • 利用CUDA加速k近鄰算法
    本次方案徵集活動詳情見:http://cuda.itpub.net/thread-1299715-1-1.html。近期活動的大部分方案,將會逐步與大家分享,不可錯過哦!  CUDA ZONE專區:http://cuda.it168.com/  CUDA技術論壇:http://cuda.itpub.net  在接觸CUDA之前,已經聽說過可以利用GPU來加速一些通用計算,也有不少人研究GPU上的通用計算(GPGPU)。
  • Python入門個人經驗之文本編譯器(IDLE、Anaconda、Pycharm)
    想在暑假好好的學習用Python做數據分析和機器學習,感覺軟體學習中遇到的問題挺多的,記不住就打算把過程寫下來。
  • 高性能Python:使用Cython
    編程派微信號:codingpy準確的說,Cython是單獨的一門語言,專門用來寫在Python裡面import用的擴展庫。實際上Cython的語法基本上跟Python一致,而Cython有專門的「編譯器」;先將 Cython代碼轉變成C(自動加入了一大堆的C-Python API),然後使用C編譯器編譯出最終的Python可調用的模塊。
  • 【技巧總結】Python 使用和高性能技巧完結
    首先,懶惰會促使程式設計師去寫一些省事兒的程序來輔助自己或別人更好的完成工作,這樣我們就無需做那些重複和繁瑣的勞動;同理能夠用3行代碼解決的事情,我們也絕不會寫出10行代碼來。其次,暴躁會讓程式設計師主動的去完成一些你還沒有提出的工作,去優化自己的代碼讓它更有效率,能夠3秒鐘完成的任務,我們絕不能容忍1分鐘的等待。
  • 將Notepad++配置為Python編譯器(方法二)
    將Notepad++配置成為腳本編譯器安裝Python, 安裝最新版本的Notepad++安裝NppExec插件;a.打開Notepad++(編輯任何一個txt文檔即可),b.<PYTHON_HOME> : 表示安裝在你本機的python的路徑,一定要帶python.exe,例如我的路徑:C:\ Python27\python.exe2. 如果給python添加了環境變量的,可以直接使用python即可.使用<PYTHON_HOM>的方便在於,如果你安裝了好幾個版本的python,那麼可以通過不同的路徑來編譯不同版本的腳本, b.
  • Python代碼加速利器:Cython
    安裝Cython首先你需要你要C編譯器。對於Linux,通常使用GNU C編譯器(gncc)。對於Mac OS,您可以下載Xcode以獲取gncc。而Windows 桌面系統下安裝C編譯器會更複雜。有了C編譯器之後,你只需運行:如何使用Cython我們將在IPython中演示Cython。我們首先介紹IPython Magic命令。
  • 實踐經驗|Python加速運行技巧 - 酷扯兒
    本文對一些 Python 代碼加速運行的技巧進行整理。0. 代碼優化原則本文會介紹不少的 Python 代碼加速運行的技巧。在深入代碼優化細節之前,需要了解一些代碼優化基本原則。第一個基本原則是不要過早優化。
  • 用GPU加速深度學習: Windows安裝CUDA+TensorFlow教程
    好消息是越來越多的深度學習框架開始支持Windows,這使得在Windows上使用GPU加速學習過程也變成了可能。很多朋友雖然沒有一塊很強勁的顯卡,但也可以以較低的代價來了解在GPU上運行深度學習模型的過程。值得欣喜的是,大部分Nvidia GeForce系列的顯卡都可以使用CUDA,大部分有獨顯的筆記本理論上都可以使用GPU來「深度學習」。