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)
Другие вопросы по тегам