2017-10-20 9 views
1

私はOpenCLで初心者です。私はこのウェブサイトからサンプルコードを取った:http://www.drdobbs.com/open-source/easy-opencl-with-python/240162614?pgno=2と私はそれを少しカスタマイズした。私はカーネルに1つの数字で満たされた4x4の行列を送り、それをカーネルから戻すことを目指しています。私はそれが簡単なコードだと知っていますが、私はOpenCLの仕組みを理解するためにこれを行う必要があります。入力行列は、このいずれかになります。PyOpenCL 2D配列のカーネルget_global_id(1)エラー

[[ 1. 1. 1. 1.] 
[ 1. 1. 1. 1.] 
[ 1. 1. 1. 1.] 
[ 1. 1. 1. 1.]] 

しかし、私はカーネルから取得出力はこの1つであり、入力と同じでなければなりません:

[[ 1. 1. 1. 1.] 
[ 0. 0. 0. 0.] 
[ 0. 0. 0. 0.] 
[ 0. 0. 0. 0.]] 

これは私の完全なコードです

import pyopencl as cl 
from pyopencl import array 
import numpy as np 

## Step #1. Obtain an OpenCL platform. 
platform = cl.get_platforms()[0] 

## It would be necessary to add some code to check the check the support for 
## the necessary platform extensions with platform.extensions 

## Step #2. Obtain a device id for at least one device (accelerator). 
device = platform.get_devices()[1] 

## It would be necessary to add some code to check the check the support for 
## the necessary device extensions with device.extensions 

## Step #3. Create a context for the selected device. 
context = cl.Context([device]) 

## Step #4. Create the accelerator program from source code. 
## Step #5. Build the program. 
## Step #6. Create one or more kernels from the program functions. 
program = cl.Program(context, """ 
    __kernel void matrix_dot_vector(const unsigned int size, __global const float *matrix, __global float *result) 
    { 
     int x = get_global_id(0); 
     int y = get_global_id(1); 
     result[x + size * y] = matrix[x + size * y]; 
    } 
    """).build() 

matrix = np.ones((4,4), np.float32) 

## Step #7. Create a command queue for the target device. 
queue = cl.CommandQueue(context) 

## Step #8. Allocate device memory and move input data from the host to the device memory. 
mem_flags = cl.mem_flags 
#matrix_buf = cl.Buffer(context, mem_flags.READ_ONLY | mem_flags.COPY_HOST_PTR, hostbuf=matrix) 
matrix_buf = cl.Buffer(context, mem_flags.READ_ONLY | mem_flags.COPY_HOST_PTR, hostbuf=matrix) 
destination_buf = cl.Buffer(context, mem_flags.WRITE_ONLY, matrix.nbytes) 

## Step #9. Associate the arguments to the kernel with kernel object. 
## Step #10. Deploy the kernel for device execution. 
program.matrix_dot_vector(queue, matrix.shape, None, np.int32(matrix.size), matrix_buf, destination_buf) 

## Step #11. Move the kernels output data to host memory. 
matrix_dot_vector = np.ones((4,4), np.float32) 
cl.enqueue_copy(queue, matrix_dot_vector, destination_buf) 

## Step #12. Release context, program, kernels and memory. 
## PyOpenCL performs this step for you, and therefore, 
## you don't need to worry about cleanup code 

print(matrix_dot_vector) 

私が見た限りでは、int y = get_global_id(1);の値は常に0です。これはエラーの原因です。カーネルに正しい形状を渡しているので、なぜそれが常に0なのか分かりません。program.matrix_dot_vector(queue, matrix.shape, None, np.int32(matrix.size), matrix_buf, destination_buf)これは第2パラメータmatrix.shapeと等しく(4,4)です。

何が問題なのでしょうか?

ありがとうございます!

答えて

2

最初のカーネルパラメータに渡される値が間違っています。サイズは合計のマトリックスサイズであってはなりません。 np.int32(matrix.size)np.int32(matrix.shape[0])に変更してください。

+0

パーフェクト!私はそれがこのようなものでなければならないことを知っていましたが、今、私がやっていたこととあなたが私に言ったことの違いを説明できますか? – kelirkenan

+0

カーネルでは、フラット化された配列内の要素の位置を計算しているので、 'x + size * y'の場合、sizeは' size = matrix.shape [0] * matrix.shape [1] 'にはなりませんが、 matrix.shape [0] 'ここで、matrix.shape [0]は最初の次元の行列サイズです。 – doqtor