一、安装numba

版本一览
os
python
llvm-dev
llvmlite
numba
ubuntu18
3.6.9
3.9
0.16
0.31
唠叨:numba依赖llvm,所以先安装llvm
brew install homebrew/versions/llvm37 --with-rtti
sudo apt-get install llvm-3.9-dev
sudo LLVM_CONFIG=/usr/bin/llvm-config-3.9 -H pip3 install llvmlite==0.16
sudo LLVM_CONFIG=/usr/bin/llvm-config-3.9 -H pip3 install numba==0.31

二、为numba配置cuda

唠叨: numba 0.47版本以下找不到cuda得自己配CUDA_HOME环境变量
【BUG 1】描述:library nvvm not found
解决:numba找不到cuda,加入环境变量让它能找到就行了
sudo vi .bashrc
内容添加如下
export CUDA_HOME=/usr/local/cuda-10.0
export LD_LIBRARY_PATH=/usr/local/cuda-10.0/lib64:$LD_LIBRARY_PATH
export PATH=/usr/local/cuda-10.0/bin:$PATH
export NUMBAPRO_NVVM=/usr/local/cuda-10.0/nvvm/lib64/libnvvm.so
export NUMBAPRO_LIBDEVICE=/usr/local/cuda-10.0/nvvm/libdevice/

【BUG 2】描述: Missing libdevice file for compute_50. 
解决:糊弄它呗
cd /usr/local/cuda/nvvm/libdevice
sudo ln -s libdevice.10.bc libdevice.compute_50.10.bc

三、动手写加速程序

参考:

3.1 传参

    提供两种方式,这种比较麻烦
@cuda.jit('void(int32[:], int32[:])')
def foo(aryA, aryB):
    ...
最方便的是auto
@cuda.autojit
def func(a,b,c):
 ... ...

3.2 返回值

以一个一维矩阵的加法为例
import operator
from numba import cuda
import numpy as np
@cuda.autojit
def add(a,b):
    for i in range(3):
        a[i] = operator.add(a[i],b[i])


c = np.array([1,2,3])
d = np.array([3,2,1])
dc = cuda.to_device(c)  # 将内存数据转到显存
dd = cuda.to_device(d)


add(dc,dd)


cc = dc.copy_to_host()   # 从显存取数据
print(cc)
返回为
[4 4 4]

3.3 线程与显存块

 每个显卡都会标注,支持多少线程,有256个的也有更多的,就拿256个的举例子,相当于16*16的矩阵

假如有1600*1600大小的矩阵要运算

就可以设置16*16的线程数,配合100*100的显存块,并行计算

from numba import cuda

@cuda.jit
def gpu_add(A,B):
    # 每个线程都会执行这个函数
    i, j = cuda.grid(2)
    A[i,j] +=B[i,j]*4+5



height = 1600
width = 1600
A = np.ones((height,width),np.float64)
B = np.ones((height,width),np.float64)

dA = cuda.to_device(A)
dB = cuda.to_device(B)

gpu_add[(100,100),(16,16)](dA,dB)


A = dA.copy_to_host()

值得注意的是,数据由内存到显存需要花费一定的时间 

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐