我有以下代码用于确认用于计算两个平方矩阵的kronecker乘积的手写方法。第一部分确实验证了我的重复和平铺a
和b
的方法分别产生相同的输出。
import pyopencl as cl
import numpy
from time import time
N = 3
num_iter = 1
a = numpy.random.rand(N,N)
b = numpy.random.rand(N,N)
c = numpy.kron(a, b)
abig = numpy.repeat(numpy.repeat(a,N,axis=1),N,axis=0)
bbig = numpy.tile(b,(N,N))
cbig = abig*bbig
print(numpy.allclose(c,cbig))
然后我尝试使用PyOpenCL将此乘法移植到GPU。我首先将biga
和bigb
分别分配为d_a
和d_b
在GPU内存上。我还在主机上将h_C
分配为空数组,并在设备上将d_C
分配为相同的大小。
context = cl.create_some_context()
queue = cl.CommandQueue(context)
h_C = numpy.empty(cbig.shape)
d_a = cl.Buffer(context, cl.mem_flags.READ_ONLY | cl.mem_flags.COPY_HOST_PTR, hostbuf=abig)
d_b = cl.Buffer(context, cl.mem_flags.READ_ONLY | cl.mem_flags.COPY_HOST_PTR, hostbuf=bbig)
d_c = cl.Buffer(context, cl.mem_flags.WRITE_ONLY, h_C.nbytes)
kernelsource = open("../GPUTest.cl").read()
program = cl.Program(context, kernelsource).build()
kronecker = program.kronecker
kronecker.set_scalar_arg_dtypes([numpy.int32, None, None, None])
for i in range(num_iter):
kronecker(queue, (N**2, N**2), None, N**2, d_a, d_b, d_c)
queue.finish()
cl.enqueue_copy(queue, h_C, d_c)
print(h_C)
以下是GPUTest.cl的内容:
__kernel void kronecker(const int N,__global float* A,__global float*B,__global float* C)
{
int i = get_global_id(0);
int j = get_global_id(1);
C[i,j] = A[i,j]*B[i,j];
}
但是,我的输出结果并非如此。我相信我的错误在于我如何处理线程ID。从阅读矩阵点产品的另一个例子来看,我的印象是ids本质上是块内元素的位置,因为这是元素,我只需要从同一位置拉出元素A和B将它们相乘。这些id是否需要组合成一个索引才能更好地解决内存实际分配的方式?
只是略有关联,但有没有办法利用平铺或内存共享方法?这只是对最简单的计算方法的一次尝试,我希望得到一种不需要a
和b
的重复/平铺版本的算法。采用a
的单个元素,将b
的整数乘以它,然后将结果存储在c
的图块中。
答案 0 :(得分:0)
问题是内核没有为输入和输出内存地址取索引。参数应该是C[i+j*N]
,以便适当地在整个内存块中移动。
答案 1 :(得分:0)
我也为kronecker产品开发了一个内核。我会把它放在这里作为参考。对于
A#B = C,
其中#是the kronecker product,A是mxn矩阵,B是pxq矩阵,C是xxy矩阵,x = m p,y = n q,以下内核将计算C:
__kernel void kroneckerProdFast(__global float* res,
__global float* a,
__global float* b,
int p,
int q){
int xi = get_global_id(0);
int x = get_global_size(0);
int yi = get_global_id(1);
int y = get_global_size(1);
int n = y / q;
int mi = xi / p;
int ni = yi / q;
int pi = xi % p;
int qi = yi % q;
res[xi * y + yi] = a[mi * n + ni] * b[pi * q + qi];
}
来自PyOpenCL的调用将是:
program.kroneckerProdFast(queue,res.shape, None, resf_buf, a_buf, b_buf,np.int32(b.shape[0]),np.int32(b.shape[1]))