1

PyOpenCL の制限を回避する方法はありますか?

array.data

で失敗します

pyopencl.array.ArrayHasOffsetError: 試行中の操作は、バッファの先頭からのオフセットで始まる配列をまだサポートしていません。

私は試した:

a.base_data[a.offset: a.offset + a.nbytes]

これは時々うまくいくようですが、それ以外の場合は次のようになります。

pyopencl.LogicError: clCreateSubBuffer が失敗しました: 無効な値

4

2 に答える 2

0

配列データの開始をマークするバッファを取得してカーネルに渡すだけの場合は、サイズを気にする必要はありません。以下は、オフセット データの先頭を指すサイズ 1 のバッファーを取得する関数です。

def data_ptr(array):
    if array.offset:
        return array.base_data.get_sub_region(array.offset, 1)
    else:
        return array.data

オフセット データの先頭へのポインターが必要な場合は、これを使用してカーネルに渡すことができます。clV配列のサブ領域をclA値 3 に設定する例を次に示します。 のデータのdata_ptr先頭へのポインターを取得するために使用します。clV

import numpy as np
import pyopencl as cl
import pyopencl.array
ctx = cl.create_some_context()
queue = cl.CommandQueue(ctx)

m, n = 5, 5
A = np.random.uniform(size=(m, n)).astype(np.float32)
clA = cl.array.Array(queue, A.shape, A.dtype)
clA.set(A)

clV = clA[1::2, 1::2]

def data(array):
    if array.offset:
        return array.base_data.get_sub_region(array.offset, 1)
    else:
        return array.data

source = """
__kernel void fn(long si, long sj, __global float *Y)
{
    const int i = get_global_id(0);
    const int j = get_global_id(1);
    Y[i*si + j*sj] = 3;
}
"""
kernel = cl.Program(ctx, source).build().fn
gsize = clV.shape
lsize = None

estrides = np.array(clV.strides) / clV.dtype.itemsize
kernel(queue, gsize, lsize, estrides[0], estrides[1], data_ptr(clV))

print(clA.get())
于 2015-09-18T20:26:08.430 に答える