当前位置: 首页 > 后端技术 > Java

使用GPU运行Python代码

时间:2023-04-01 23:25:09 Java

介绍前几天,我摆弄了一下Ubuntu。我只是想在我的旧电脑上使用N卡。我可以用GPU跑代码,体验多核的乐趣。还好我的破电脑也支持Cuda:$sudolshw-Cdisplay*-displaydescription:3Dcontrollerproduct:GK208M[GeForceGT740M]vendor:NVIDIACorporationphysicalid:0businfo:pci@0000:01:00.0version:a1宽度:64位时钟:33MHz功能:pmmsipciexpressbus_mastercap_listrom配置:driver=nouveaulatency=0resources:irq:35memory:f0000000-f0ffffffmemory:c0000000-cffffffff0ff-port:d0000size=128)安装相关工具首先安装Cuda开发工具,命令如下:$sudoaptinstallnvidia-cuda-toolkit查看相关信息:$nvcc--versionnvcc:NVIDIA(R)CudacompilerdriverCopyright(c)2005-2021NVIDIACorporationBuiltonThu_Nov_18_09:45:30_PST_2021Cuda编译工具,release11.5,V11.5.119Buildcuda_11.5.r11.5/compiler.30672275_0通过Conda安装相关依赖:condainstallnumba&condainstallcuda,同理。测试和驱动安装简单测试了一下,报错:$/home/larry/anaconda3/bin/python/home/larry/code/pkslow-samples/python/src/main/python/cuda/test1.pyTraceback(最近调用最后):文件“/home/larry/anaconda3/lib/python3.9/site-packages/numba/cuda/cudadrv/driver.py”,第246行,在ensure_initializedself.cuInit(0)文件“/home/larry/anaconda3/lib/python3.9/site-packages/numba/cuda/cudadrv/driver.py”,第319行,在safe_cuda_api_callself._check_ctypes_error(fname,retcode)文件“/home/larry/anaconda3/lib/python3.9/site-packages/numba/cuda/cudadrv/driver.py”,第387行,在_check_ctypes_errorraiseCudaAPIError(retcode,msg)numba.cuda.cudadrv.driver.CudaAPIError:[100]CalltocuInitresults在CUDA_ERROR_NO_DEVICED处理上述异常的过程中,又发生了一个异常:Traceback(mostrecentcalllast):File"/home/larry/code/pkslow-samples/python/src/main/python/cuda/test1.py",line15,在<模块>gpu_print[1,2]()文件“/home/larry/anaconda3/lib/python3.9/site-packages/numba/cuda/compiler.py”,第862行,在__getitem__返回self.configure(*args)文件“/home/larry/anaconda3/lib/python3.9/site-packages/numba/cuda/compiler.py”,第857行,在配置返回_KernelConfiguration(self,griddim,blockdim,stream,sharedmem)文件“/home/larry/anaconda3/lib/python3.9/site-packages/numba/cuda/compiler.py”,第718行,在__init__ctx=get_context()文件“/home/larry/anaconda3/lib/python3.9/site-packages/numba/cuda/cudadrv/devices.py”,第220行,在get_context中返回_runtime.get_or_create_context(devnum)文件“/home/larry/anaconda3/lib/python3.9/site-packages/numba/cuda/cudadrv/devices.py”,第138行,在get_or_create_context返回self._get_or_create_context_uncached(devnum)文件“/home/larry/anaconda3/lib/python3.9/site-packages/numba/cuda/cudadrv/devices.py”,第1行53、在_get_or_create_context_uncached中使用driver.get_active_context()作为ac:文件“/home/larry/anaconda3/lib/python3.9/site-packages/numba/cuda/cudadrv/driver.py”,第487行,在__enter__驱动程序中。cuCtxGetCurrent(byref(hctx))文件“/home/larry/anaconda3/lib/python3.9/site-packages/numba/cuda/cudadrv/driver.py”,第284行,在__getattr__self.ensure_initialized()文件“/home/larry/anaconda3/lib/python3.9/site-packages/numba/cuda/cudadrv/driver.py”,第250行,在ensure_initializedraiseCudaSupportError(f“Erroratdriverinit:{description}”)numba.cuda.cudadrv.error.CudaSupportError:Erroratdriverinit:CalltocuInitresultsinCUDA_ERROR_NO_DEVICE(100)网上搜索了下,发现是驱动问题通过Ubuntu自带的工具安装显卡驱动:还是失败:$nvidia-smiNVIDIA-SMI因为无法与NVIDIA驱动通讯而失败。确保已安装并运行最新的NVIDIA驱动程序。最后通过命令行安装Driver,成功解决了这个问题:$sudoaptinstallnvidia-driver-470检查后发现正常:$nvidia-smiWedDec722:13:492022+--------------------------------------------------------------------------+|NVIDIA-SMI470.161.03驱动版本:470.161.03CUDA版本:11.4||------------------------------+----------------------+----------------------+|GPU名称持久性-M|总线IDDisp.A|挥发性Uncorr。电子通信委员会||风扇温度性能功率:使用/上限|内存使用|GPU-Util计算M.||||MIGM.||=================================+=======================+========================||0NVIDIAGeForce...关闭|00000000:01:00.0不适用|不适用||不适用51CP8不适用/不适用|4MiB/2004MiB|N/A默认||||不适用|+--------------------------------+---------------------+--------------------++--------------------------------------------------------------------------+|进程:||GPUGICIPID类型进程名称GPU内存||IDID使用||==================================================================================||未找到正在运行的进程|+------------------------------------------------------------------------+测试代码也能运行测试Python代码打印ID准备如下代码:fromnumbaimportcudaimportosdefcpu_print():print('cpuprint')@cuda.jitdefgpu_print():dataIndex=cuda.threadIdx.x+cuda.blockIdx.x*cuda.blockDim.xprint('gpuprint',cuda.threadIdx.x,cuda.blockIdx.x,cuda.blockDim.x,dataIndex)if__name__=='__main__':gpu_print[4,4]()cuda.synchronize()cpu_print()的代码主要有两个功能,一个由CPU执行,一个由GPU执行,进行打印操作。关键在于@cuda.jit注解,它可以让代码在GPU上执行。运行结果如下:$/home/larry/anaconda3/bin/python/home/larry/code/pkslow-samples/python/src/main/python/cuda/print_test.pygpuprint03412gpuprint13413gpu打印23414gpu打印33415gpu打印0248gpu打印1249gpu打印22410gpu打印32411gpu打印0144gpu打印1145gpu打印2146gpu打印3147gpuprint0040gpuprint1041gpuprint2042gpuprint3043cpuprint可以看到GPU一共打印了16次,使用不同的Thread来执行。这次每次打印的结果可能都不一样,因为提交给GPU是异步执行的,没办法保证先执行哪个单元。同时,还需要调用同步函数cuda.synchronize(),保证GPU执行后继续运行。检查时间我们可以通过这个函数看到GPU并行的强大功能:fromnumbaimportjit,cudaimportnumpyasnp#tomeasureexectimefromtimeitimportdefault_timerastimer#normalfunctiontorunoncpudeffunc(a):foriinrange(10000000):a[i]+=1#functionoptimizedtorunongpu@jit(target_backend='cuda')deffunc2(a):foriinrange(10000000):a[i]+=1if__name__=="__main__":n=10000000a=np.ones(n,dtype=np.float64)start=timer()func(a)print("withoutGPU:",timer()-start)start=timer()func2(a)print("withGPU:",timer()-start)结果如下:$/home/larry/anaconda3/bin/python/home/larry/code/pkslow-samples/python/src/main/python/cuda/time_test.pywithoutGPU:3.7136273959999926withGPU:0.4040513340000871可以看出使用CPU需要3.7秒,但是使用GPU只需要0.4秒,还是快了很多。当然,这并不是说GPU一定比CPU快,这取决于任务的类型。代码参见GitHub:https://github.com/LarryDpk/p...