Как передать массив векторов в pyOpenCL

Я перемещаю симуляцию в pyOpenCL и не могу получить доступ к данным для работы. Я пытаюсь предоставить одномерный массив векторов (ну, на самом деле несколько, но в примере, который я включил, используется только один).

В настоящее время несколько векторов копируются просто отлично, но тогда данные просто не те, что я предоставил.

Я не думаю, что писал здесь раньше, поэтому извиняюсь, если какое-либо форматирование/представление неверно. Кроме того, я только что удалил весь код моделирования, поэтому я понимаю, что этот код в настоящее время на самом деле ничего не делает, я просто хочу правильно передать буфер.

Заранее спасибо.

Ядро (kertest.py):

step1 = """
#pragma OPENCL EXTENSION cl_amd_printf: enable
#define X xdim
#define Y ydim
__kernel void k1(__global float3 *spins,
                 __local float3 *tile)
{        
    ushort lid = 2 * get_local_id(0);
    ushort group = 2 * get_group_id(0);
    ushort num = get_num_groups(0);
    int lim = X*Y*3;

    for (ushort i = 0; i < lim; i++)
        {
            if (lid == 0 && group == 0)
            {
                printf("%f :: %d\\n", spins[i].x, i);
            }
         }
}"""

Сам код (gputest.py):

import kertest as k2D
import numpy as np
import pyopencl as cl

class GPU_MC2DSim():
    def __init__(self, x, y):
        self.x = x
        self.y = y

        if x >= y:
            self.xdim = int(self.x)
            self.ydim = int(self.y)
        else:
            self.xdim = int(self.y)
            self.ydim = int(self.x)

        if self.xdim % 2 != 0: self.xdim += 1

        if self.ydim % 2 != 0: self.ydim += 1

        self.M = np.ones((self.xdim*self.ydim, 3)).astype(np.float32)
        self.M[:, 1] += 1.0
        self.M[:, 2] += 2.0

        print self.M

    def simulate(self):
        ctx = cl.create_some_context()
        q = cl.CommandQueue(ctx)
        mf = cl.mem_flags

        #Pass buffer:
        M_buf = cl.Buffer(ctx, mf.READ_WRITE | mf.COPY_HOST_PTR, hostbuf = self.M)

        #Insert kernel parameters:
        params = {"xdim" : "%d" % (self.xdim),
                  "ydim" : "%d" % (self.ydim),
                  }
        for name in params:
            k2D.step1 = k2D.step1.replace(name, params[name])

        #Compile kernel:
        step1 = cl.Program(ctx, k2D.step1).build()

        locmem = cl.LocalMemory(self.xdim*4*4)

        step1.k1(q, ((self.xdim*self.ydim)/4,), (self.xdim/2,), M_buf, locmem).wait()
        return None

xdim = 4
ydim = 4
sim = GPU_MC2DSim(xdim, ydim)
sim.simulate()

person JustinD    schedule 31.07.2012    source источник


Ответы (1)


Ваш код для копирования данных на устройство просто в порядке. Однако у вашего ядра есть как минимум две проблемы:

  1. #P2# <блочная цитата> #P3# #P4#
  2. Расчет лимита int lim = X*Y*3; немного неверен. Вы уже пытаетесь читать из массива float3, поэтому *3 лишнее.

Решение обеих проблем простое: как указано в спецификации, вы должны использовать vload3 для загрузки из массива floats:

#pragma OPENCL EXTENSION cl_amd_printf: enable
#define X xdim
#define Y ydim
__kernel void k1(__global float *spins,
                 __local float3 *tile)
{
    ushort lid = 2 * get_local_id(0);
    ushort group = 2 * get_group_id(0);
    ushort num = get_num_groups(0);
    int lim = X*Y;

    for (ushort i = 0; i < lim; i++)
        {
            if (lid == 0 && group == 0)
            {
                float3 vec = vload3(i, spins);
                printf("(%f, %f, %f) :: %d\\n", vec.x, vec.y, vec.z, i);
            }
         }
}
person reima    schedule 31.07.2012