numba学習チュートリアル

8729 ワード

一、pythonの基礎紹介
Pythonは、科学、エンジニアリング、データ分析アプリケーションに広く使用されている効率的な動的プログラミング言語です.pythonの普及に影響を与える要因は多く、清潔で、表現力に富んだ文法と標準データ構造、全面的な「バッテリー含む」標準ライブラリ、優秀なドキュメント、広範な図書館とツール生態系、専門サポートの可用性、および大きく開放的なコミュニティを含む.しかし、最も重要なのは、Pythonのような動的タイプ化解釈言語が効率的であることかもしれない.Pythonは柔軟で柔軟で、高速プロトタイプ設計の理想的な言語となり、同時に完全なシステムを構築する理想的な言語でもある.しかし、Pythonの最大の利点は、柔軟性とタイプのない高度な構文がデータとコンピューティングの密集したプログラムのパフォーマンスを低下させる可能性があるという最大の弱点かもしれません.
二、numba-高性能高効率の計算
この記事では、CUDAをサポートするGPUまたはマルチコアCPU上で実行するためにPythonコードをコンパイルできるAnacondaからのPythonコンパイラNumbaについて説明します.Pythonは通常コンパイル言語ではないので、なぜPythonコンパイラを使用するのか知りたいかもしれません.答えはもちろん、ネイティブコンパイルコードを実行することは、動的解釈コードを実行するよりも何倍も速いです.Numbaでは、実行時にコンパイルできるPython関数のタイプ署名を指定できます(「インスタント」または「JITコンパイル」です).Numbaがコードを動的にコンパイルする能力は、Pythonの柔軟性を放棄しないことを意味します.これは効率的なプログラミングと高性能計算に理想的な組み合わせを提供する重要な一歩である.    
Numbaを使用すると、標準のPython関数を記述し、CUDAをサポートするGPU上で実行できるようになりました.Numbaは、広く使用されているNumPyライブラリのように、アレイ向けのコンピューティングタスクのために設計されています.アレイ向けコンピューティングタスクにおけるデータ並列性はGPUなどのアクセラレータに非常に適している.NumbaはNumPy配列タイプを理解し、GPUまたはマルチコアCPU上で実行するために有効なコンパイルコードを生成する.必要なプログラミング作業は、NumbaがGPUのコンパイルであることを示すために、関数装飾器を追加するように簡単に行うことができる.たとえば、以下のコードの@vectorizeアクセラレータは、GPU上でデータ配列を並列に処理するために使用できるように、実行時にスカラー関数Addのコンパイル済みベクトル化バージョンを生成します.
imort 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加速ライブラリCUDA並列コンピューティングプラットフォームの利点の一つは、その広範なGPU加速ライブラリである.Numbaチームのもう一つのpyculibというプロジェクトはCUDA cuBLAS(密集線形代数)、cuFFT(高速フーリエ変換)、cuRAND(乱数生成)ライブラリにPythonインタフェースを提供しています.多くのアプリケーションは、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は、実行時にCUDA Python関数をコンパイルし、使用するタイプに特化しています.CUDA Python APIは、データ転送およびCUDAストリームの明示的な制御、およびその他の機能を提供します.
次のコード例では、簡単なMandelbrot設定カーネルを使用してこの点を示します.注意してください、mandel_kernel関数はNumbaが提供するcudaを用いる.threadIdx,cuda.blockIdx,cuda.blockDimとcuda.gridDim構造は、現在のスレッドのグローバルXおよびYピクセルインデックスを計算する.他のCUDA言語と同様に、関数名とパラメータリストの間に「実行構成」(CUDA-はカーネルを実行するためのスレッド数とスレッド数を表す)を挿入することでカーネルを起動します:mandel_kernel [griddim,blockdim]( -  2.0,1.0,-1.0,1.0,d_image,20). to_の使用も表示されますhostとto_デバイスAPI関数は、GPUにデータをコピーするか、GPUからデータをコピーします.
@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)
On a server with an NVIDIA Tesla P100 GPU and an Intel Xeon E5-2698 v3 CPU, this CUDA Python Mandelbrot code runs nearly 1700 times faster than the pure Python version. 1700x may seem an unrealistic speedup, but keep in mind that we are comparing compiled, parallel, GPU-accelerated Python code to interpreted, single-threaded Py

NVIDIA Tesla P 100 GPUとIntel Xeon E 5-2698 v 3 CPUを搭載したサーバでは、このCUDA Python Mandelbrotコードの実行速度は純Python版より1700倍近く速い.1700 xは非現実的に見えるかもしれませんが、コンパイルされた、パラレル、GPU加速のPythonコードとCPUで説明された単一スレッドPythonコードを比較していることを覚えておいてください.
四、直ちにNumba Numbaの使用を開始し、Pythonの開発者にGPU加速計算に簡単にアクセスする方法と、ますます複雑なCUDAコードを使用し、最小限の新しい文法と用語を使用する方法を提供した.簡単な関数アクセラレータから、関数を自動的にコンパイルしたり、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 install numba cudatoolkit pyculibインストールに必要なCUDAパッケージを入力します.次に、ContinuumIO githubリポジトリでCumbAのNumbaチュートリアルを表示します.また、AnacondaブログのNumba投稿を参照することをお勧めします.
転載先:https://www.cnblogs.com/Cucucudeblog/p/10653928.html