PyOpencl - неверные аргументы переданы Kernell
Я с трудом выполняю базовую скалярную операцию с 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 как общее для всех работников, я хочу поместить их в глобальную память один раз, чтобы каждый работник мог получить к ней доступ вместо повторения значения для каждый работник.
Я считаю, что это должно быть действительно просто, но я новичок в параллельных вычислениях и не знаю, как это исправить.
Спасибо.
1 ответ
Все объекты, содержащиеся в одном массиве, имеют общий тип данных. Этот тип данных указан в атрибуте 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)