Python GPU编程之入门篇

Python 2015-12-24

现在GPU编程正变得越来越流行,由于CPU串行执行的局限性,程序如果在GPU上运行,则可真正做到多线程,并发执行,极大减少运行时间,这对于分秒必争的科学计算,以及新兴的人工智能领域都带来了极大的便利。 目前,GPU编程以NVIDIA的CUDA平台为主,支持四种语言C、C++、Fortran(PGI)以及Python。目前CUDA的最新版本已经达到7.5,具体配置可以看官方指导和其它教程,这里不做具体介绍。 下面我们具体来看Python的GPU编程。 我的显卡是GeForce GT 740M,安装CUDA7.5,使用Python2.7搭配相关库。 首先我们要引入一些必要的包 from numbapro import cuda 是cuda包是必须导入的,否则不能使用GPU。 引入之后就可以调用cuda对象了。例如,创建一个一维网格

tx = cuda.threadIdx.x
bx = cuda.blockIdx.x
bw = cuda.blockDim.x
i = tx + bx * bw
array[i] = something(i)

也可以简化成

i = cuda.grid(1)
array[i] = something(i)

上面两段代码实现的功能是一样的。

接下来我们了解一下CUDA Stream的操作 CUDA流是对CUDA设备的命令队列,通过特殊的流,CUDA API可以变为异步,这也意味着请求肯在队列结束前返回。存储器传送指令和内核调用都可以使用CUDA流。 下面我们来看示例:

 stream = cuda.stream()
devary = cuda.to_device(an_array, stream=stream)
a_cuda_kernel[griddim, blockdim, stream](devary)
cuda.copy_to_host(an_array, stream=stream)
# 在an_array中的数据可能尚未就绪
stream.synchronize()
# an_array中的数据已经就绪

另一种语法是使用Python环境

stream = cuda.stream()
with stream.auto_synchronize():
    devary = cuda.to_device(an_array, stream=stream)
    a_cuda_kernel[griddim, blockdim, stream](devary)
    devary.copy_to_host(an_array, stream=stream)
# an_array中的数据已经就绪

接下来是关于共享内存: 为了达到最大性能,CUDA内核需要使用共享内存用于缓存数据,CUDA编译器支持使用cuda.shared.array(shape, dtype)方法用来指定使用内核中的对象。 下面看一个例子

   bpg = 50
tpb = 32
n = bpg * tpb

@jit(argtypes=[float32[:,:], float32[:,:], float32[:,:]], target='gpu')
def cu_square_matrix_mul(A, B, C):
    sA = cuda.shared.array(shape=(tpb, tpb), dtype=float32)
    sB = cuda.shared.array(shape=(tpb, tpb), dtype=float32)

    tx = cuda.threadIdx.x
    ty = cuda.threadIdx.y
    bx = cuda.blockIdx.x
    by = cuda.blockIdx.y
    bw = cuda.blockDim.x
    bh = cuda.blockDim.y

    x = tx + bx * bw
    y = ty + by * bh

    acc = 0.
    for i in range(bpg):
        if x < n and y < n:
            sA[ty, tx] = A[y, tx + i * tpb]
            sB[ty, tx] = B[ty + i * tpb, x]

        cuda.syncthreads()

        if x < n and y < n:
            for j in range(tpb):
                acc += sA[ty, j] * sB[j, tx]

        cuda.syncthreads()

    if x < n and y < n:
        C[y, x] = acc

以上就是python GPU编程的入门介绍。


本文由 Tony 创作,采用 知识共享署名 3.0,可自由转载、引用,但需署名作者且注明文章出处。

如果对您有用,您的支持将鼓励我继续创作!