2017-03-29 54 views
0

我尝试用numba来使用cuda python。 代码是计算1D数组的总和如下,但我不知道如何得到一个值的结果,而不是三个值。为什么我不能用numba(cuda python)获得正确的1D数组的总和?

python3.5与numba + CUDA8.0

import os,sys,time 
import pandas as pd 
import numpy as np 
from numba import cuda, float32 

os.environ['NUMBAPRO_NVVM']=r'D:\NVIDIA GPU Computing Toolkit\CUDA\v8.0\nvvm\bin\nvvm64_31_0.dll' 
os.environ['NUMBAPRO_LIBDEVICE']=r'D:\NVIDIA GPU Computing Toolkit\CUDA\v8.0\nvvm\libdevice' 

bpg = (1,1) 
tpb = (1,3) 

@cuda.jit 
def calcu_sum(D,T): 
    ty = cuda.threadIdx.y 
    bh = cuda.blockDim.y 
    index_i = ty 
    L = len(D) 
    su = 0 
    while index_i<L: 
     su +=D[index_i] 
     index_i +=bh 
    print('su:',su) 
    T[0,0]=su 
    print('T:',T[0,0]) 


D = np.array([ 0.42487645,0.41607881,0.42027071,0.43751907,0.43512794,0.43656972, 
       0.43940639,0.43864551,0.43447691,0.43120232], dtype=np.float32) 
T = np.empty([1,1]) 
print('D: ',D) 

stream = cuda.stream() 
with stream.auto_synchronize(): 
    dD = cuda.to_device(D, stream) 
    dT= cuda.to_device(TE, stream) 
    calcu_sum[bpg, tpb, stream](dD,dT) 

输出是:

D: [ 0.42487645 0.41607881 0.42027071 0.43751907 0.43512794 0.43656972 
    0.43940639 0.43864551 0.43447691 0.43120232] 
su: 1.733004 
su: 1.289852 
su: 1.291317 
T: 1.733004 
T: 1.289852 
T: 1.291317 

为什么我不能得到输出 “4.31417383”,而不是 “1.733004 1.289852 1.291317” ? 1.733004 + 1.289852 + 1.291317 = 4.314173。

我是新来的numba,阅读numba文档,但不知道该怎么做。有人可以提供建议吗?

+0

我对你的问题所作的编辑是语法正确的英语。请不要将它们改回到毫无意义的事情上。 – talonmies

回答

1

你没有得到你期望的总和的原因是你没有编写代码来产生这个总和。

基本的CUDA编程模型(无论使用CUDA C,Fortran还是Python作为您的语言)都是您编写由每个线程执行的内核代码。你已经为每个线程编写代码来读取和求和输入数组的一部分。你还没有为这些线程编写任何代码来将他们各自的部分总和分成总和。

非常有极其这样做的算法 - 它被称为并行减少。您可以在每个版本的CUDA工具箱的示例中找到PDF格式的算法介绍,或者下载关于它的演示文稿here。您还可以阅读使用CUDA的更新功能(经线洗牌指令和原子事务处理)的算法的更现代版本here

在研究了简化算法后,您需要将标准CUDA C内核代码调整为Numba Python内核方言。在最低限度,这样的事情:

tpb = (1,3) 

@cuda.jit 
def calcu_sum(D,T): 

    ty = cuda.threadIdx.y 
    bh = cuda.blockDim.y 
    index_i = ty 
    sbuf = cuda.shared.array(tpb, float32) 

    L = len(D) 
    su = 0 
    while index_i < L: 
     su += D[index_i] 
     index_i +=bh 

    print('su:',su) 

    sbuf[0,ty] = su 
    cuda.syncthreads() 

    if ty == 0: 
     T[0,0] = 0 
     for i in range(0, bh): 
      T[0,0] += sbuf[0,i] 
     print('T:',T[0,0]) 

可能会做你想要什么,尽管它仍然是一个最佳的并行共享内存减少了漫长的道路,因为当你阅读我提供的链接材料,你会看到至。

+0

谢谢。我会研究它。 – glen

相关问题