Как передать структуру C с массивами и переменными в ядро ​​OpenCL, используя PyOpenCL

Итак, я должен передать некоторые данные в ядро ​​OpenCL с помощью PyOpenCL или некоторые обходные пути с использованием Python. Данные читаются на стороне ядра как структура, и я не могу изменить ядро, потому что оно работает нормально и является частью гораздо большего проекта, с которым должен работать мой код.

Ядро выглядит так:

typedef struct VglClStrEl{
float data[VGL_ARR_CLSTREL_SIZE];
int ndim;
int shape[VGL_ARR_SHAPE_SIZE];
int offset[VGL_ARR_SHAPE_SIZE];
int size;
} VglClStrEl;

typedef struct VglClShape{
int ndim;
int shape[VGL_ARR_SHAPE_SIZE];
int offset[VGL_ARR_SHAPE_SIZE];
int size;
} VglClShape;

__kernel void kernel(__global unsigned char* img_input,
__global unsigned char* img_output,
__constant VglClShape* img_shape,
__constant VglClStrEl* window)
{

// do what is needed

}

Итак, как вы можете видеть, структуры VglClShape и VglClStrEl имеют разные типы массивов и переменные static-bitize.

Обходной путь [1] поддерживает структуры только с массивами одного типа (или мне, к сожалению, не удалось найти способ сделать это с несколькими типами массивов).

Обходной путь [2] — это ссылка на документацию PyOpenCL для передачи данных Python в структуру ядра OpenCL. Этот подход вообще не поддерживает массивы.

Итак, как я могу передать данные Python, которые может прочитать ядро ​​OpenCL? У меня уже есть все данные на стороне Python, и мне просто нужно знать, как передать их из Python в ядро.

Прежде чем спросить: я использую Python 3 и Я не могу изменить ядро.

И да, размеры массива статичны. Вы можете предположить что-то подобное:

VGL_ARR_CLSTREL_SIZE=256;
VGL_ARR_SHAPE_SIZE=20;
[1] Передача структуры с указателями на ядро ​​OpenCL с помощью PyOpenCL

[2] https://documen.tician.de/pyopencl/howto.html#how-to-use-struct-types-with-pyopencl

0

Решение

Есть хакерский способ сделать это, который требует утомительного спора байтов. Предположительно, вы в порядке с развертыванием небольшого зондирующего ядра OpenCL? (PyOpenCL делает это под капотом для некоторых операций в любом случае)

Основная идея заключается в том, чтобы:

  • узнайте, как устройство OpenCL выравнивает все элементы ваших структур, запустив ядро ​​одного экземпляра
  • создать массив пустых байтов, соответствующий размеру структуры OpenCL
  • побайтно скопируйте каждый элемент вашей структуры Python в этот массив
  • при вызове вашего неизменяемого ядра OpenCL, передайте этот массив через мешок байтового буфера

Следующее ядро ​​делает работу:

__kernel void get_struct_sizes( __global uint *struct_sizes )
{
const uint global_id = get_global_id(0u)+get_global_id(1u)*get_global_size(0u);
VglClStrEl vgclstrel;
VglClShape vgclshape;
uint offset;

printf("In GPU (probing):\n Kernel instance = %d\n", global_id);

if (global_id==0) {
offset = (uint)&(vgclstrel.data);
struct_sizes[0] = (uint)sizeof(vgclstrel);
struct_sizes[1] = (uint)&(vgclstrel.ndim)-offset;
struct_sizes[2] = (uint)&(vgclstrel.shape)-offset;
struct_sizes[3] = (uint)&(vgclstrel.offset)-offset;
struct_sizes[4] = (uint)&(vgclstrel.size)-offset;
offset = (uint)&(vgclshape.ndim);
struct_sizes[5] = (uint)sizeof(vgclshape);
struct_sizes[6] = (uint)&(vgclshape.shape)-offset;
struct_sizes[7] = (uint)&(vgclshape.offset)-offset;
struct_sizes[8] = (uint)&(vgclshape.size)-offset;
}
return;
}

Запустите это ядро ​​и вернитесь struct_sizes в vgclshape_sizesсоздайте этот массив:

img_shape  = np.zeros((vgclshape_sizes[0]), dtype=np.uint8)

и скопируйте в него то, что вам нужно:

def copy_into_byte_array(value, byte_array, offset):
for i,b in enumerate(np.ndarray.tobytes(value)):
byte_array[i+offset] = b
copy_into_byte_array(ndim,   img_shape, 0)
copy_into_byte_array(shape,  img_shape, vgclshape_sizes[1])
copy_into_byte_array(offset, img_shape, vgclshape_sizes[2])
copy_into_byte_array(size,   img_shape, vgclshape_sizes[3])

Я пропустил несколько шагов здесь; заполнив их, вы обнаружите, что этот подход работает. Я смог передать демонстрационную структуру фиктивной копии вашего нерушимого ядра.

Мне было бы интересно услышать, есть ли более изящные способы сделать любой / все эти шаги. Я также ожидаю, что будут проблемы с порядком байтов и т. Д., Которые в противном случае были бы прозрачными. Если повезет, вы можете обойти их.

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]