基本上没有资料,实践了很长时间才掌握基本用法。
官网示例
#! /usr/bin/env python3 import pyopencl as cl import numpy as np a_np = np.random.rand(10**7).astype(np.float32) b_np = np.random.rand(10**7).astype(np.float32) ctx = cl.create_some_context() queue = cl.CommandQueue(ctx) mf = cl.mem_flags a_g = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=a_np) b_g = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=b_np) prg = cl.Program(ctx, r""" __kernel void sum( __global const float *a_g, __global const float *b_g, __global float *res_g) { int gid = get_global_id(0); res_g[gid] = a_g[gid] + b_g[gid]; } """).build() res_g = cl.Buffer(ctx, mf.WRITE_ONLY, a_np.nbytes) knl = prg.sum # Use this Kernel object for repeated calls knl(queue, a_np.shape, None, a_g, b_g, res_g) res_np = np.empty_like(a_np) cl.enqueue_copy(queue, res_np, res_g) # Check on CPU with Numpy: # print(res_np - (a_np + b_np)) # print(np.linalg.norm(res_np - (a_np + b_np))) assert np.allclose(res_np, a_np + b_np)
解析
Pyopencl程序的大概流程为:
1.通过pyopencl.create_some_context构建一个类似会话的对象ctx
2.基于ctx构建queue对象
3.以ctx为参数,用pyopencl.Buffer拷贝Python数据到显卡缓存中
4.以ctx为参数,通过pyopencl.Program(script).build()编译c语言,通过编译对象的属性获取c函数(如示例的prg.sum)
5.以queue为参数,运行c函数
6.以queue为参数,将结果从显存拷贝到Python数据结构中
参数含义
运行c函数时,需要在前面额外传入三个参数,如示例中的knl(prg.sum)函数,它们分别为:
- queue对象
- 需要启动的线程大小(一个元组,代表各维度的大小,最小为一维,如(100,))
- 未知
其中第二个参数如果大于实际使用的数量,会报错,因为后面的线程根据gid取的数据地址不存在,然而这不影响最终结果。
报错:找不到平台
在Windows下没安装任何平台,没有遇见过报错,然而在没有显卡的linux平台上,遇见了下面的报错:
pyopencl._cl.LogicError: clGetPlatformIDs failed: PLATFORM_NOT_FOUND_KHR
意思是找不到OpenCL能运行的环境。
有的机器能用python的oclgrind包作为虚拟环境,有的却不能,可能要安装英特尔的官方opencl驱动才能用。
标签:mf,cl,Pyopencl,res,ctx,用法,queue,np From: https://www.cnblogs.com/roundfish/p/17075631.html