Python是一种高效的动态编程语言,广泛用于科学、工程和数据分析应用程序。python如此受欢迎的因素有很多,包括其干净、富有表现力的语法和标准数据结构、全面的“内置电池”标准库、出色的文档、广泛的库和工具生态系统、专业支持的可用性以及庞大而开放的社区。不过,也许最重要的原因是像Python这样的动态类型解释型语言可以提供更高的生产力。Python足够敏捷和灵活,使其成为一种用于快速原型设计和构建完整系统的优秀语言。但Python最大的优势也可能是它最大的弱点:它的灵活性和无类型的高级语法可能导致数据和计算密集型程序的性能不佳。出于这个原因,关心效率的Python程序员经常用C重写他们最内层的循环,并从Python调用编译后的C函数。有很多项目旨在简化这种优化,例如Cython,但这通常需要学习一种新的语法。理想情况下,Python程序员希望在不使用其他编程语言的情况下使他们现??有的Python代码更快,当然许多人也希望使用加速器来获得更高的性能。Numba:HighProductivityforHighPerformanceComputing在本文中,作者将向您介绍Numba,这是一个来自Anaconda的Python编译器,它可以在支持CUDA的GPU或多核cpu上编译Python代码。Python通常不是编译语言,您可能想知道为什么要使用Python编译器。答案当然是:运行本地编译代码比运行动态解释代码快很多倍。Numba允许您为Python函数指定类型签名,从而在运行时启用编译(这是“即时”、即时或JIT编译)。Numba动态编译代码的能力意味着您不会失去Python的灵活性。这是向提供高生产力编程和高性能计算的完美结合迈出的一大步。使用Numba编写标准Python函数并在支持CUDA的GPU上运行它们。Numba专为面向数组的计算任务而设计,很像常用的NumPy库。在面向数组的计算任务中,数据并行对于GPU等加速器来说是很自然的。Numba理解NumPy数组类型并使用它们生成高效的编译代码以在GPU或多核CPU上执行。所需的编程工作可以像添加函数装饰器一样简单,以指示Numba为GPU编译。例如,在下面的代码中,@vectorize装饰器生成标量函数的编译矢量化版本,该版本在运行时添加,以便它可用于在GPU上并行处理数据数组。importnumpyasnpfromnumbaimportvectorize@vectorize(['float32(float32,float32)'],target='cuda')defAdd(a,b):returna+b#InitializearraysN=100000A=np.ones(N,dtype=np.float32)B=np.ones(A.shape,dtype=A.dtype)C=np.empty_like(A,dtype=A.dtype)#AddarraysonGPUC=Add(A,B)要在CPU上编译和运行相同的函数,我们只需目标需要更改为“CPU”,这将带来编译级别的性能,在CPU上矢量化C代码。这种灵活性可以帮助您生成更多可重用的代码,并允许您在没有GPU的机器上进行开发。Python的GPU加速库CUDA并行计算平台的优势之一是可用的GPU加速库的广度。Numba团队的另一个项目叫做pyculib,它为CUDAcuBLAS(密集线性代数,denselinearalgebra)、cuFFT(FastFourierTransform,快速傅里叶变换)和cuRAND(随机数生成,随机数生成器)提供了Python接口图书馆。许多应用程序可以通过使用这些库而显着加速,而无需编写任何特定于GPU的代码。例如,下面的代码使用“XORWOW”伪随机数生成器在GPU上生成100万个均匀分布的随机数。importnumpyasnpfrompyculibimportrandascurandprng=curand.PRNG(rndtype=curand.PRNG.XORWOW)rand=np.empty(100000)prng.uniform(rand)printrand[:10]CUDAPython的高并行性Anaconda(以前称为ContinuumAnalytics)在实现这些计算的高速需要一个更具表现力的编程接口,该接口比库和自动循环矢量化更详细地控制并行性。因此,Numba具有另一组重要的特性,这些特性构成了它的非正式名称“CUDAPython”。Numba公开了CUDA编程模型,就像CUDAC/C++一样,但使用纯python语法,以便程序员可以创建自定义的、经过调优的并行内核,而不会放弃python带来的便利和优势。Numba的CUDAJIT(可通过装饰器或函数调用使用)在运行时专门针对您使用的类型编译CUDAPython函数,其CUDAPythonAPI提供对数据传输和CUDA流的显式控制,以及其他功能。以下代码示例演示了一个简单的Mandelbrot安装内核。请注意,mandel_kernel函数使用Numba提供的cuda.threadIdx、cuda.blockIdx、cuda.blockDim和cuda.gridDim架构来计算当前线程的全局X和Y像素索引。与其他CUDA语言一样,我们通过在函数名称和参数列表之间的括号内插入“执行配置”(CUDA线程计数和线程块)来启动内核:mandel_kernel[griddim,blockdim](-2.0,1.0、-1.0、1.0、d_image、20)。您还可以看到使用to_host和to_deviceAPI函数从GPU复制数据。Mandelbrot的示例将在Github上持续更新。@cuda.jit(device=True)defmandel(x,y,max_iters):"""Giventherealandimaginarypartsofacomplexnumber,determineifitisacandidateformembershippintheMandelbrotsetgivenafixednumberofiterations."""c=complex(x,y)z=0.0jforiinrange(max_iters):z=z*z+cif(z.real*z.real+z.imag*z.imag)>=4:returnireturnmax_iters@cuda.jitdefmandel_kernel(min_x,max_x,min_y,max_y,image,iters):height=image.shape[0]宽度=image.shape[1]pixel_size_x=(max_x-min_x)/widthpixel_size_y=(max_y-min_y)/heightstartX=cuda.blockDim.x*cuda.blockIdx.x+cuda.threadIdx.xstartY=cuda.blockDim.y*cuda.blockIdx.y+cuda.threadIdx.ygridX=cuda.gridDim.x*cuda.blockDim.x;gridY=cuda.gridDim.y*cuda.blockDim.y;forxinrange(startX,width,gridX):real=min_x+x*pixel_size_xforyinrange(startY,height,gridY):imag=min_y+y*pixel_size_yimage[y,x]=mandel(real,imag,iters)gimage=np.zeros((1024,1536),dtype=np.uint8)blockdim=(32,8)griddim=(32,16)start=timer()d_image=cuda.to_device(gimage)mandel_kernel[griddim,blockdim](-2.0,1.0,-1.0,1.0,d_image,20)d_image.to_host()dt=timer()-startprint"MandelbrotcreatedonGPUin%fs"%dtimshow(gimage)在带有NVIDIATeslaP100的GPU上它可能在配备IntelXeonE5-2698v3CPU的服务器上,此CUDAPythonMandelbrot代码的运行速度比纯Python版本快1700倍似乎不切实际,但请记住,我们正在比较编译的、并行的、GPU加速的Python代码以解释单线程CPU上的Python代码。今天开始使用NumbaNumba为Python开发人员提供了一种进入GPU加速计算的简单方法,以及一种处理日益复杂的CUDA代码的方法,至少使用了一些新的语法和术语。您可以从一个简单的函数装饰器开始自动编译函数,或者使用pyculib强大的CUDA库。当你提高对并行编程概念的理解,当你需要对并行线程进行富有表现力和灵活的控制时,CUDA就可以使用,而不需要你在第一天就完全理解它。Numba是一个BSD认证的开源项目,它本身在很大程度上依赖于LLVM编译器的功能。Numba的GPU后端使用基于LLVM的NVIDIACompilerSDK。CUDA库周围的pyculib包装器也是开源和BSD认证的。要开始使用Numba,第一步是下载并安装AnacondaPython发行版,这是一个“用于大规模数据处理、预测分析和科学计算的完全免费的Python发行版”,其中包括许多流行的软件包(Numpy、Scipy、Matplotlib、iPython等)和强大的包管理器“conda”。安装Anaconda后,通过键入condainstallnumbacudatoolkitpyculib安装所需的CUDA包。然后在ContinuumIOgithub存储库中查看CUDA的Numba教程。
