我很难用PyOpenCl进行基本的标量操作 基本上,我想要做的是,给定一个浮点型数组,将每个数组元素乘以标量浮点数并将结果放在一个新的缓冲区上。这应该很容易,但由于某种原因,它并没有像它应该的那样萎缩。
这是我正在使用的代码:(带有_h的变量是HOST变量;带有_g的变量是设备变量)
import numpy as np
import pyopencl as cl
# Device Init
ctx = cl.create_some_context()
queue = cl.CommandQueue(ctx)
MF = cl.mem_flags
# Host Initial Variables
a_h = np.array([1.0, 2.0, 3.0, 4.0])
b_h = np.float32(2.0)
# DEVICE Variable Allocation
a_g = cl.Buffer(ctx, MF.READ_ONLY | MF.COPY_HOST_PTR, hostbuf=a_h)
c_g = cl.Buffer(ctx, MF.WRITE_ONLY, a_h.nbytes)
# DEVICE's Kernel - Multiply each element of the array a_g by the scalar b_g and put the result on the array c_g
source = """
__kernel void mult(float b_g, __global float *a_g, __global float *c_g){
const int gid = get_global_id(0);
c_g[gid] = b_g * a_g[gid];
}
"""
prg = cl.Program(ctx, source).build()
prg.mult(queue, a_h.shape, None, b_h, a_g, c_g)
# Export The Result On The DEVICE Back To The HOST
c_h = np.empty_like(a_h)
cl.enqueue_copy(queue, c_h, c_g)
# Output
print c_h
预期的输出是
[2.0 4.0 6.0 8.0]
这是输出:
[ 2.56000000e+002 5.12000000e+002 -1.73777009e+308 -1.73777009e+308]
我不明白为什么。我已经尝试过阅读PyOpenCL项目页面,但实际上我并不是很了解它。 我想我没有正确地执行内核部分或内核调用部分。
我尝试过使用内核:
__kernel void mult(__global float *b_g, __global float *a_g, __global float *c_g)
但是正如预期的那样它没有用,因为我没有为b_g创建指针,也不知道如何创建一个指针。错误是:
:2:39: error: parameter may not be qualified with an address space
__kernel void mult(__global float b_g, __global float *a_g, __global float *c_g){
^
我背后的主要想法很简单:因为我将把这个值b_g用作所有工作者的常用东西,我想把它们放在全局内存上一次,这样每个工作者都可以访问它而不是重复每个工人的价值。
我相信这应该非常简单,但我是并行计算的新手,并且不知道如何解决这个问题。
谢谢。
答案 0 :(得分:0)
在numpy中,同一数组中包含的所有对象都具有公共数据类型。此数据类型在数组的属性dtype
中指定。 (numpy.array doc,numpy datatypes)
数组a_h
中的数据类型为float64
(64位浮点数)。由于您的内核需要32位浮点数(float32
),因此它会像这样解释a_h
的数据。所以它会看到8个32位浮点数而不是4个64位浮点数。
要使其工作,请将a_h
中的对象存储为float32
。因此,将其定义如下:
a_h = np.array([[1.0, 2.0, 3.0, 4.0], dtype=np.float32)