如何在PyOpenCL中从矩阵的每一行中减去一个数组?

时间:2018-08-05 16:07:37

标签: python opencl gpu pyopencl

我想将相同尺寸的数组1xN减去尺寸为MxN的矩阵的每一行。即,执行numpy时执行相同的操作a-b,前者是矩阵,后者是数组。例如:

import pyopencl as cl
import pyopencl.array as cl_array
import numpy as np

a = np.matrix('1 2 3; 4 5 6').astype(np.float32)
b = np.array([1,2,3]).astype(np.float32)

ctx = cl.create_some_context()
queue = cl.CommandQueue(ctx)
a_dev = cl_array.to_device(queue, a)
b_dev = cl_array.to_device(queue, b)
dest_dev = cl_array.empty_like(a_dev)

prg = cl.Program(ctx, """
    __kernel void fun(
                    const unsigned int size,
                    __global const float *a,
                    __global const float *b,
                    __global float *c)
    {
      int i = get_global_id(0);
      int j = get_global_id(1);
      c[i + j*size] = a[i + j*size] - b[j];
    }
    """).build()

prg.fun(queue, a.shape, None, np.int32(len(a)), a_dev.data, b_dev.data, dest_dev.data)
print(dest_dev)

我认为该内核将返回矩阵

[0 0 0 ; 3 3 3]

但实际上它返回

[0 1 1 ; 2 2 3]

哪里出了错?

1 个答案:

答案 0 :(得分:1)

您必须在内核中交换矩阵计算的行和列。您可以使用

a.shape           # returns tuple(rows, columns)

返回。它返回(2, 3)而不是(3, 2)。因此,更改内核中的行,即可在其中对矩阵进行计算:

c[j + i*size] = a[j + i*size] - b[j];

在这种情况下,i是行数,j是列数。

将矩阵的size赋予内核时,也会出错。代替

 np.int32(len(a)) 

返回2的行数(y轴)。将内核启动行更改为:

prg.fun(queue, a.shape, None, np.int32(a.shape[1]), a_dev.data, b_dev.data, dest_dev.data)

a.shape[1]为您提供矩阵第二维的大小,即示例中的列数3。

还可以使用Work-Item内置函数查询内核本身中的列数:

 unsigned int size = get_global_size(1);   // size of the 2. dim of the kernel

在这种情况下,您不必将列数作为内核参数传递。