首頁 >後端開發 >Python教學 >使用Python寫CUDA程式的方法詳細介紹

使用Python寫CUDA程式的方法詳細介紹

高洛峰
高洛峰原創
2017-03-28 09:29:194269瀏覽

下面小編就為大家帶來一篇使用Python寫CUDA程式的方法。小編覺得蠻不錯的,現在就分享給大家,也給大家做個參考。一起跟著小編過來看看吧

使用Python寫CUDA程式有兩種方式:

##* Numba

* PyCUDA

numbapro現在已經不建議使用了,功能被分割並分別整合到accelerate和Numba了。

範例

numba

Numba透過及時編譯機制( JIT)最佳化Python程式碼,Numba可以針對本機的硬體環境進行最佳化,同時支援CPU和GPU的最佳化,並且可以和Numpy集成,使Python程式碼可以在GPU上運行,只需在

函數上方加上相關的指令標記,

如下:#

import numpy as np 
from timeit import default_timer as timer
from numba import vectorize
@vectorize(["float32(float32, float32)"], target='cuda')
def vectorAdd(a, b):
  return a + b
def main():
  N = 320000000
  A = np.ones(N, dtype=np.float32 )
  B = np.ones(N, dtype=np.float32 )
  C = np.zeros(N, dtype=np.float32 )
  start = timer()
  C = vectorAdd(A, B)
  vectorAdd_time = timer() - start
  print("c[:5] = " + str(C[:5]))
  print("c[-5:] = " + str(C[-5:]))
  print("vectorAdd took %f seconds " % vectorAdd_time)
if name == 'main':
  main()

PyCUDA

PyCUDA的核心函數(kernel)其實就是使用C/C++編寫的,透過動態編譯為GPU微碼,Python程式碼與GPU程式碼進行交互,如下所示:

import pycuda.autoinit
import pycuda.driver as drv
import numpy as np
from timeit import default_timer as timer
from pycuda.compiler import SourceModule
mod = SourceModule("""
global void func(float *a, float *b, size_t N)
{
 const int i = blockIdx.x * blockDim.x + threadIdx.x;
 if (i >= N)
 {
  return;
 }
 float temp_a = a[i];
 float temp_b = b[i];
 a[i] = (temp_a * 10 + 2 ) * ((temp_b + 2) * 10 - 5 ) * 5;
 // a[i] = a[i] + b[i];
}
""")
func = mod.get_function("func")  
def test(N):
  # N = 1024 * 1024 * 90  # float: 4M = 1024 * 1024
  print("N = %d" % N)
  N = np.int32(N)
  a = np.random.randn(N).astype(np.float32)
  b = np.random.randn(N).astype(np.float32)  
  # copy a to aa
  aa = np.empty_like(a)
  aa[:] = a
  # GPU run
  nTheads = 256
  nBlocks = int( ( N + nTheads - 1 ) / nTheads )
  start = timer()
  func(
      drv.InOut(a), drv.In(b), N,
      block=( nTheads, 1, 1 ), grid=( nBlocks, 1 ) )
  run_time = timer() - start 
  print("gpu run time %f seconds " % run_time)  
  # cpu run
  start = timer()
  aa = (aa * 10 + 2 ) * ((b + 2) * 10 - 5 ) * 5
  run_time = timer() - start 
  print("cpu run time %f seconds " % run_time) 
  # check result
  r = a - aa
  print( min(r), max(r) )
def main():
 for n in range(1, 10):
  N = 1024 * 1024 * (n * 10)
  print("------------%d---------------" % n)
  test(N)
if name == 'main':
  main()

對比

numba使用一些指令標記某些函數來加速(也可以使用Python編寫內核函數),這點類似OpenACC,而PyCUDA需要自己寫kernel ,在運行時進行編譯,底層是基於C/C++實現的。透過測試,這兩種方式的加速比基本上差不多。但是,numba更像黑盒,不知道內部到底做了什麼,而PyCUDA就顯得很直觀。因此,這兩種方式有不同的應用:

* 如果只是為了加速自己的演算法而不關心CUDA編程,那麼直接使用numba會更好。

* 如果為了學習、研究CUDA程式或實驗某一個演算法在CUDA下的可行性,那麼就使用PyCUDA。

* 如果寫的程式將來要移植到C/C++,那麼就一定要使用PyCUDA了,因為使用PyCUDA寫的kernel本身就是用CUDA C/C++寫的。

以上是使用Python寫CUDA程式的方法詳細介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn