溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

怎么使用Python3+pycuda實現(xiàn)執(zhí)行簡單GPU計算任務(wù)

發(fā)布時間:2023-03-14 10:49:41 來源:億速云 閱讀:261 作者:iii 欄目:開發(fā)技術(shù)

今天小編給大家分享一下怎么使用Python3+pycuda實現(xiàn)執(zhí)行簡單GPU計算任務(wù)的相關(guān)知識點,內(nèi)容詳細(xì),邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。

技術(shù)背景

GPU的加速技術(shù)在深度學(xué)習(xí)、量子計算領(lǐng)域都已經(jīng)被廣泛的應(yīng)用。其適用的計算模型是小內(nèi)存的密集型計算場景,如果計算的模型內(nèi)存較大,則需要使用到共享內(nèi)存,這會直接導(dǎo)致巨大的數(shù)據(jù)交互的運(yùn)算量,通信開銷較大。因為pycuda的出現(xiàn),也使得我們可以直接在python內(nèi)直接使用GPU函數(shù),當(dāng)然也可以直接在python代碼中集成一些C++的代碼,用于構(gòu)建GPU計算的函數(shù)。

pycuda環(huán)境配置

pycuda的安裝環(huán)境很大程度上取決約顯卡驅(qū)動本身是否能夠安裝成功,除了安裝pycuda庫本身之外,重點是需要確保如下的指令可以運(yùn)行成功:

[dechin@dechin-manjaro pycuda]$ nvidia-smi
Sun Mar 21 20:26:43 2021       
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 455.45.01    Driver Version: 455.45.01    CUDA Version: 11.1     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                               |                      |               MIG M. |
|===============================+======================+======================|
|   0  GeForce MX250       Off  | 00000000:3C:00.0 Off |                  N/A |
| N/A   48C    P0    N/A /  N/A |      0MiB /  2002MiB |      0%      Default |
|                               |                      |                  N/A |
+-------------------------------+----------------------+----------------------+
                                                                               
+-----------------------------------------------------------------------------+
| Processes:                                                                  |
|  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
|        ID   ID                                                   Usage      |
|=============================================================================|
|  No running processes found                                                 |
+-----------------------------------------------------------------------------+

上述返回的結(jié)果是一個沒有GPU任務(wù)情況下的展示界面,包含有顯卡型號、顯卡內(nèi)存等信息。如果存在執(zhí)行的任務(wù),則顯示結(jié)果如下案例所示:

[dechin@dechin-manjaro pycuda]$ nvidia-smi
Sun Mar 21 20:56:04 2021       
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 455.45.01    Driver Version: 455.45.01    CUDA Version: 11.1     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                               |                      |               MIG M. |
|===============================+======================+======================|
|   0  GeForce MX250       Off  | 00000000:3C:00.0 Off |                  N/A |
| N/A   47C    P0    N/A /  N/A |     31MiB /  2002MiB |      0%      Default |
|                               |                      |                  N/A |
+-------------------------------+----------------------+----------------------+
                                                                               
+-----------------------------------------------------------------------------+
| Processes:                                                                  |
|  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
|        ID   ID                                                   Usage      |
|=============================================================================|
|    0   N/A  N/A     18427      C   python3                            29MiB |
+-----------------------------------------------------------------------------+

我們發(fā)現(xiàn)這里多了一個pid為18427的python的進(jìn)程正在使用GPU進(jìn)行計算。在運(yùn)算過程中,如果任務(wù)未能夠執(zhí)行成功,有可能在內(nèi)存中遺留一個進(jìn)程,這需要我們自己手動去釋放。最簡單粗暴的方法就是:直接使用kill -9 pid來殺死殘留的進(jìn)程。我們可以使用pycuda自帶的函數(shù)接口,也可以自己寫C++代碼來實現(xiàn)GPU計算的相關(guān)功能,當(dāng)然一般情況下更加推薦使用pycuda自帶的函數(shù)。以下為一部分已經(jīng)實現(xiàn)的接口函數(shù),比如gpuarray的函數(shù):

怎么使用Python3+pycuda實現(xiàn)執(zhí)行簡單GPU計算任務(wù)

再比如cumath的函數(shù):

怎么使用Python3+pycuda實現(xiàn)執(zhí)行簡單GPU計算任務(wù)

使用GPU計算向量指數(shù)

對于一個向量的指數(shù)而言,其實就是將每一個的向量元素取指數(shù)。當(dāng)然,這與前面一篇關(guān)于量子門操作的博客中介紹的矩陣指數(shù)略有區(qū)別,這點要注意區(qū)分。

在下面的示例中,我們對比了numpy中實現(xiàn)的指數(shù)運(yùn)算和pycuda中實現(xiàn)的指數(shù)運(yùn)算。

# array_exp.py
 
import pycuda.autoinit
import pycuda.gpuarray as ga
import pycuda.cumath as gm
import numpy as np
import sys
 
if sys.argv[1] == '-l':
    length = int(sys.argv[2]) # 從命令行獲取參數(shù)值
 
np.random.seed(1)
array = np.random.randn(length).astype(np.float32)
array_gpu = ga.to_gpu(array)
 
exp_array = np.exp(array)
print (exp_array)
exp_array_gpu = gm.exp(array_gpu)
gpu_exp_array = exp_array_gpu.get()
print (gpu_exp_array)

這里面我們計算一個隨機(jī)向量的指數(shù),向量的維度length是從命令行獲取的一個參數(shù),上述代碼的執(zhí)行方式和執(zhí)行結(jié)果如下所示:

[dechin@dechin-manjaro pycuda]$ python3 array_exp.py -l 5
[5.0750957  0.5423974  0.58968204 0.34199178 2.3759744 ]
[5.075096   0.5423974  0.58968204 0.34199178 2.3759747 ]

我們先確保兩者計算出來的結(jié)果是一致的,這里我們可以觀察到,兩個計算的結(jié)果只保障了7位的有效數(shù)字是相等的,這一點在大部分的場景下精度都是有保障的。接下來我們使用timeit來統(tǒng)計和對比兩者的性能:

# array_exp.py
 
import pycuda.autoinit
import pycuda.gpuarray as ga
import pycuda.cumath as gm
import numpy as np
import sys
import timeit
 
if sys.argv[1] == '-l':
    length = int(sys.argv[2])
 
np.random.seed(1)
array = np.random.randn(length).astype(np.float32)
array_gpu = ga.to_gpu(array)
 
def npexp():
    exp_array = np.exp(array)
 
def gmexp():
    exp_array_gpu = gm.exp(array_gpu)
    # gpu_exp_array = exp_array_gpu.get()
 
if __name__ == '__main__':
    n = 1000
    t1 = timeit.timeit('npexp()', setup='from __main__ import npexp', number=n)
    print (t1)
    t2 = timeit.timeit('gmexp()', setup='from __main__ import gmexp', number=n)
    print (t2)

這里也順便介紹一下timeit的使用方法:這個函數(shù)的輸入分別是:函數(shù)名、函數(shù)的導(dǎo)入方式、函數(shù)的重復(fù)次數(shù)。這里需要特別說明的是,如果在函數(shù)的導(dǎo)入方式中,不使用__main__函數(shù)進(jìn)行導(dǎo)入,即使是本文件下的python函數(shù),也是無法被導(dǎo)入成功的。在輸入的向量達(dá)到一定的規(guī)模大小時,我們發(fā)現(xiàn)在執(zhí)行時間上相比于numpy有非常大的優(yōu)勢。當(dāng)然還有一點需要注意的是,由于我們測試的是計算速度,原本使用了get()函數(shù)將GPU中計算的結(jié)果進(jìn)行導(dǎo)出,但是這部分其實不應(yīng)該包含在計算的時間內(nèi),因此后來又注釋掉了。具體的測試數(shù)據(jù)如下所示:

[dechin@dechin-manjaro pycuda]$ python3 array_exp.py -l 10000000
26.13127974300005
3.469969915000547

以上就是“怎么使用Python3+pycuda實現(xiàn)執(zhí)行簡單GPU計算任務(wù)”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學(xué)習(xí)更多的知識,請關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI