Numpy 使用OpenCL优化代替多处理池映射

Numpy 使用OpenCL优化代替多处理池映射,numpy,gpu,opencl,python-multiprocessing,pyopencl,Numpy,Gpu,Opencl,Python Multiprocessing,Pyopencl,在我的代码的第一个版本中,我使用了python的多处理库,应用于16个线程上的主函数main\u LOOP,如下所示: def MAIN_LOOP(lll, seed=None): global aa global bb aa, bb = 0,0 if paramo == 0: C_ij_GG, C_ij_LL, C_ij_GL = np.zeros((len(zrange), len(zrange))), np.zeros((len(zrange

在我的代码的第一个版本中,我使用了python的多处理库,应用于16个线程上的主函数
main\u LOOP
,如下所示:

def MAIN_LOOP(lll, seed=None):
    global aa
    global bb
    aa, bb = 0,0
    if paramo == 0:
        C_ij_GG, C_ij_LL, C_ij_GL = np.zeros((len(zrange), len(zrange))), np.zeros((len(zrange), len(zrange))), np.zeros((len(zrange), len(zrange)))
    C_ij_GG_up, C_ij_LL_up, C_ij_GL_up = np.zeros((len(zrange), len(zrange))), np.zeros((len(zrange), len(zrange))), np.zeros((len(zrange), len(zrange)))
    C_ij_GG_dw, C_ij_LL_dw, C_ij_GL_dw = np.zeros((len(zrange), len(zrange))), np.zeros((len(zrange), len(zrange))), np.zeros((len(zrange), len(zrange)))
    while aa < len(zrange):
        while bb < len(zrange):
            if paramo == 0:
                C_ij_GG[aa][bb], C_ij_LL[aa][bb], C_ij_GL[aa][bb] = Pobs_C(zpm, zrange[aa], zrange[bb], h[2], Omega_m[2], Omega_DE[2], w0[2], wa[2], C_IA, A_IA[2], n_IA[2], B_IA[2], E_tab, R_tab, DG_tab, DG_tab, WG_tab, W_tab, WIA_tab, l[lll], P_dd_C, R_tab(z_pk)) 
            C_ij_GG_up[aa][bb], C_ij_LL_up[aa][bb], C_ij_GL_up[aa][bb] = Pobs_C(zpm, zrange[aa], zrange[bb], h[0], Omega_m[0], Omega_DE[0], w0[0], wa[0], C_IA, A_IA[0], n_IA[0], B_IA[0], E_tab_up, R_tab_up, DG_tab, DG_tab_up, WG_tab_up, W_tab_up, WIA_tab_up, l[lll], P_dd_C_up, R_tab_up(z_pk))
            C_ij_GG_dw[aa][bb], C_ij_LL_dw[aa][bb], C_ij_GL_dw[aa][bb] = Pobs_C(zpm, zrange[aa], zrange[bb], h[3], Omega_m[3], Omega_DE[3], w0[3], wa[3], C_IA, A_IA[3], n_IA[3], B_IA[3], E_tab_dw, R_tab_dw, DG_tab, DG_tab_dw, WG_tab_dw, W_tab_dw, WIA_tab_dw, l[lll], P_dd_C_dw, R_tab_dw(z_pk))
            bb=bb+1
        bb=0
        aa=aa+1
        
    if paramo == 0:
        aa, bb = 0,0 
        outGG=open(pre_CC_path[0]+CC_path[2]+"/COVAR_fid_"+str(l[lll]),'w')
        outLL=open(pre_CC_path[1]+CC_path[2]+"/COVAR_fid_"+str(l[lll]),'w')
        outGL=open(pre_CC_path[2]+CC_path[2]+"/COVAR_fid_"+str(l[lll]),'w')
        while aa < len(C_ij_GG):
            while bb < len(C_ij_GG):
                outGG.write(str("%.16e" % C_ij_GG[aa][bb]))
                outGG.write(str(' '))
                outLL.write(str("%.16e" % C_ij_LL[aa][bb]))
                outLL.write(str(' '))
                outGL.write(str("%.16e" % C_ij_GL[aa][bb]))
                outGL.write(str(' '))
                bb=bb+1
            outGG.write(str('\n'))
            outLL.write(str('\n'))
            outGL.write(str('\n'))
            bb=0
            aa=aa+1
        outGG.close()
        outLL.close()
        outGL.close()
    
    aa, bb = 0,0            
    outGGU=open(pre_CC_path[0]+CC_path[0]+"/COVAR_up_"+str(l[lll]),'w')
    outGGD=open(pre_CC_path[0]+CC_path[3]+"/COVAR_dw_"+str(l[lll]),'w')
    outLLU=open(pre_CC_path[1]+CC_path[0]+"/COVAR_up_"+str(l[lll]),'w')
    outLLD=open(pre_CC_path[1]+CC_path[3]+"/COVAR_dw_"+str(l[lll]),'w')
    outGLU=open(pre_CC_path[2]+CC_path[0]+"/COVAR_up_"+str(l[lll]),'w')
    outGLD=open(pre_CC_path[2]+CC_path[3]+"/COVAR_dw_"+str(l[lll]),'w')
    while aa < len(C_ij_GG_up):
        while bb < len(C_ij_GG_up):
            outGGU.write(str("%.16e" % C_ij_GG_up[aa][bb]))
            outGGU.write(str(' '))
            outGGD.write(str("%.16e" % C_ij_GG_dw[aa][bb]))
            outGGD.write(str(' '))
            outLLU.write(str("%.16e" % C_ij_LL_up[aa][bb]))
            outLLU.write(str(' '))
            outLLD.write(str("%.16e" % C_ij_LL_dw[aa][bb]))
            outLLD.write(str(' '))
            outGLU.write(str("%.16e" % C_ij_GL_up[aa][bb]))
            outGLU.write(str(' '))
            outGLD.write(str("%.16e" % C_ij_GL_dw[aa][bb]))
            outGLD.write(str(' '))
            bb=bb+1
        outGGU.write(str('\n'))
        outGGD.write(str('\n'))
        outLLU.write(str('\n'))
        outLLD.write(str('\n'))
        outGLU.write(str('\n'))
        outGLD.write(str('\n'))
        bb=0
        aa=aa+1
    outGGU.close()
    outGGD.close()
    outLLU.close()
    outLLD.close()
    outGLU.close()
    outGLD.close()
    lll=lll+1
    
lll = range(len(l))    
if __name__ == '__main__':          
    pool = mp.Pool(16)
    pool.map(MAIN_LOOP, lll)
现在,我尝试使用另一种优化方法,并尝试通过GPU/OpenCL进行优化:

因此,我用以下内容代替了并行化的
多处理池
代码部分:

# NEW VERSION : with OpenCL

if __name__ == '__main__':          
  # GPU/OPenCL VERSION
  # Select a device
  ctx = cl.create_some_context()
  queue = cl.CommandQueue(ctx)
  # Kernel
  prg = cl.Program(ctx, """
  typedef int T;

  // Extern MAIN_LOOP function
  void MAIN_LOOP(__global T* in);

  __kernel
  void
  gpu_map(__global T* in, 
         const size_t n)
  {
    unsigned gid = get_global_id(0);

    // Call MAIN_LOOP with global_id
    MAIN_LOOP(in[gid]);
  }
  """).build()

  # Output compiler
  os.environ['PYOPENCL_COMPILER_OUTPUT'] = '1'
  # Allocate memory on the device and copy the content of our numpy array
  mf = cl.mem_flags
  # Get kernel function
  lll_np = np.array(lll, dtype=np.uint32)
  # Create input numpy
  lll_g = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=lll_np)
  #Get kernel function
  my_knl= prg.gpu_map
  my_knl.set_scalar_arg_dtypes([None, np.int32])
  my_knl(queue, lll_np.shape, None, lll_g, len(lll_np))
不幸的是,无法构建内核程序,我遇到以下错误:

Traceback (most recent call last):X2_non_flat_GPU_dev.py
  File "X2_non_flat_GPU_OpenCL_dev.py", line 671, in <module>
    """).build()
  File "/Users/fab/Library/Python/2.7/lib/python/site-packages/pyopencl/__init__.py", line 510, in build
    options_bytes=options_bytes, source=self._source)
  File "/Users/fab/Library/Python/2.7/lib/python/site-packages/pyopencl/__init__.py", line 554, in _build_and_catch_errors
    raise err
pyopencl._cl.RuntimeError: clBuildProgram failed: BUILD_PROGRAM_FAILURE - clBuildProgram failed: BUILD_PROGRAM_FAILURE - clBuildProgram failed: BUILD_PROGRAM_FAILURE

Build on <pyopencl.Device 'AMD Radeon Pro Vega 20 Compute Engine' on 'Apple' at 0x1021d00>:

Error returned by cvms_element_build_from_source
(options: -I /Users/fab/Library/Python/2.7/lib/python/site-packages/pyopencl/cl)
(source saved as /var/folders/y7/5dtgdjld5fxd3c1qm9hknlm40000gn/T/tmpg3pfTx.cl)
Traceback(最近一次调用last):X2\u non\u flat\u GPU\u dev.py
文件“X2_non_flat_GPU_OpenCL_dev.py”,第671行,在
“”“).build()
文件“/Users/fab/Library/Python/2.7/lib/Python/site packages/pyopencl/_init__.py”,第510行,内部版本
选项\字节=选项\字节,源=自身。\源)
文件“/Users/fab/Library/Python/2.7/lib/Python/site-packages/pyopencl/_-init__.py”,第554行,在“构建”和“捕获”错误中
提出错误
pyopencl.\u cl.RuntimeError:clBuildProgram失败:构建程序失败-clBuildProgram失败:构建程序失败-clBuildProgram失败:构建程序失败
基于:
cvms_元素_构建_从_源返回的错误
(选项:-I/Users/fab/Library/Python/2.7/lib/Python/site-packages/pyopencl/cl)
(源另存为/var/folders/y7/5dtgdjld5fxd3c1qm9hknlm40000gn/T/tmpg3pfTx.cl)
关于这些错误有什么线索吗

更新1 关于我的代码的基准测试,类似的奖励已经开始了:on


从运行时的角度来看,有更多关于贪婪代码部分的信息。但是,这项奖励更多的是关于如何找到优化方法的一般想法。

在OpenCL中,您有一个主机(在您的情况下,您的CPU执行Python代码)和多个设备(通常是一个GPU)

要由设备执行的主机排队操作:

  • 创建缓冲区
  • 将数据保存到缓冲区中
  • 执行内核
  • 从缓冲区中检索结果
  • 一些同步机制(屏障…) [此列表并非详尽无遗]
假设您的CPU只有几个处理器,在当前的台式计算机中通常是8-32个。但是您的GPU有很多处理器(例如,在我的例子中是4096个内核)

这个巨大的差异(32到4K)意味着GPU对于某些任务的速度要快得多,但是CPU线程和GPU线程之间不能进行任何一对一的同步。我的意思是,CPU可以在GPU上启动多个线程并检索结果,但GPU线程不能调用CPU线程(因为您将有128个GPU内核试图调用CPU的同一个内核,这将非常慢,对吗?)

总结:如果
MAIN\u LOOP
是主机上的一个函数,则不能从内核内部调用它。这在OpenCL、CUDA、OpenGL或任何其他类似技术中都是不可能的(并且可能会保持多年)

但是,您可以做的是:

  • 调用内核并将
    MAIN\u循环的索引保存在缓冲区中
  • 在Python中,等待内核完成,对检索到的每个索引执行
    MAIN\u循环

  • 但是,如果您试图从OpenCL内核调用Python代码,那么恐怕除了将
    MAIN\u循环
    转换为OpenCL内核代码之外,您别无选择。

    即使您的主机程序是使用PyOpenCL用Python编写的,您的OpenCL内核也必须用or编写。这是没有办法的。看看是否您希望使用Python编写在GPU上运行的代码。

    我不确定您会问多少次相同的问题——您不能使用PyCUDA或PyOpenCLI在GPU上运行Python,您完全理解,答案是您不能“将外部函数与此内核代码进行接口”“--基本的想法是荒谬和不可能的错误并不能说明很多,主要是你的opencl内核有错误。@youpilat13:你所说的“外部函数”到底是什么意思?如果你试图从opencl调用一个主机函数,你就不能!(而且你不想,因为这会让所有GPU线程等待你的几个CPU线程)。解决方案是完成内核的执行,之后,您可以对结果进行一些CPU计算。您可以“优化”什么如果代码中有GPU?它看起来是对其他Python函数的一系列调用,然后是文件I/O。GPU不能进行文件I/O,而且可能它们也不能运行其他Python函数。你一直问的所有这些问题都是徒劳的。仅仅因为某个函数很慢,并不意味着你可以用一个GPU@AdrienMarire.感谢您的帮助,我将尝试将
    MAIN\u LOOP
    的所有内容实现到内核代码中,甚至包括(重新编译或调整)内核代码中的所有小子函数(在函数定义之前是否需要关键字
    static
    )。这可能是一项艰巨的任务,但如果我想要GPU优化,我别无选择……不,内核内部函数不需要
    静态
    Traceback (most recent call last):X2_non_flat_GPU_dev.py
      File "X2_non_flat_GPU_OpenCL_dev.py", line 671, in <module>
        """).build()
      File "/Users/fab/Library/Python/2.7/lib/python/site-packages/pyopencl/__init__.py", line 510, in build
        options_bytes=options_bytes, source=self._source)
      File "/Users/fab/Library/Python/2.7/lib/python/site-packages/pyopencl/__init__.py", line 554, in _build_and_catch_errors
        raise err
    pyopencl._cl.RuntimeError: clBuildProgram failed: BUILD_PROGRAM_FAILURE - clBuildProgram failed: BUILD_PROGRAM_FAILURE - clBuildProgram failed: BUILD_PROGRAM_FAILURE
    
    Build on <pyopencl.Device 'AMD Radeon Pro Vega 20 Compute Engine' on 'Apple' at 0x1021d00>:
    
    Error returned by cvms_element_build_from_source
    (options: -I /Users/fab/Library/Python/2.7/lib/python/site-packages/pyopencl/cl)
    (source saved as /var/folders/y7/5dtgdjld5fxd3c1qm9hknlm40000gn/T/tmpg3pfTx.cl)