pyOpenCL 向量类型的 numpy 数组与浮点数的 numpy 数组之间的交互
Interaction between numpy arrays of pyOpenCL vector types and numpy arrays of floats
我发现使用结构和 np.ndarrays 使用像 pyopencl.cltypes.float2 这样的 dtypes 非常方便。这是将结构化数据传递到我的内核的一种清晰且自我记录的方式,而不是一堆浮点数。
但是我发现某些行为不方便。例如给定:
import numpy as np
import pyopencl.cltypes as cltp
a = np.zeros((3,5), dtype=cltp.float2)
>>> a
array([[(0., 0.), (0., 0.), (0., 0.), (0., 0.), (0., 0.)],
[(0., 0.), (0., 0.), (0., 0.), (0., 0.), (0., 0.)],
[(0., 0.), (0., 0.), (0., 0.), (0., 0.), (0., 0.)]],
dtype=[(('x', 's0'), '<f4'), (('y', 's1'), '<f4')])
我可以在将数据结构传递给内核之前逐步构建我的数据结构,例如
a[:,1] = (42,-42)
>>> a
array([[( 0., 0.), (42., -42.), ( 0., 0.), ( 0., 0.), ( 0., 0.)],
[( 0., 0.), (42., -42.), ( 0., 0.), ( 0., 0.), ( 0., 0.)],
[( 0., 0.), (42., -42.), ( 0., 0.), ( 0., 0.), ( 0., 0.)]],
dtype=[(('x', 's0'), '<f4'), (('y', 's1'), '<f4')])
这很好。但是我也想将大小为 2 的数组分配给 float2,但这失败了。
a[:,1] = np.array((42,-42))
ValueError: could not broadcast input array from shape (2) into shape (3)
我不得不这样做
a[:,1]['x'] = 42
a[:,1]['y'] = -42
这行得通,但有点违背了整个事情的目的。
我是否遗漏了一些明显的语法差异,或者这个功能不应该以这种方式使用?
编辑: 在我试图展示最简单的例子时,我把问题简单化了。 hpaulj 的回答是正确的,因为如果我在 shape=(2,) 的某些东西上使用显式 dtype=float2,它将转换为 dtype=float2 的 shape=(1,)。
然而,我的实际问题更为笼统,关于如何从 array(shape=(foo, bar, N), dtype=np.float32) 到 array(shape=(foo, bar), dtype=cltp.floatN) N=2,3,4.
刚刚出现的后续问题:是否一定会出现实际副本,还是可以转换'in place'?实际的内存布局乍一看是兼容的。
In [99]: a=np.array([[(0., 0.), (0., 0.), (0., 0.), (0., 0.), (0., 0.)],
...: [(0., 0.), (0., 0.), (0., 0.), (0., 0.), (0., 0.)],
...: [(0., 0.), (0., 0.), (0., 0.), (0., 0.), (0., 0.)]],
...: dtype=[(('x', 's0'), '<f4'), (('y', 's1'), '<f4')])
In [100]: a.dtype
Out[100]: dtype([(('x', 's0'), '<f4'), (('y', 's1'), '<f4')])
In [101]: a.dtype.fields
Out[101]:
mappingproxy({'s0': (dtype('float32'), 0, 'x'),
'x': (dtype('float32'), 0, 'x'),
's1': (dtype('float32'), 4, 'y'),
'y': (dtype('float32'), 4, 'y')})
查看预期目标,一个具有复合数据类型的 3 元素数组:
In [102]: a[:,1]
Out[102]:
array([(0., 0.), (0., 0.), (0., 0.)],
dtype=[(('x', 's0'), '<f4'), (('y', 's1'), '<f4')])
虽然你的数组是 2 元素 int。使用此构造,使用元组不会改变任何内容。
In [103]: np.array((42,-42))
Out[103]: array([ 42, -42])
但是如果我们指定了正确的 dtype,我们将创建一个 0d 数组:
In [104]: np.array((42,-42), a.dtype)
Out[104]: array((42., -42.), dtype=[(('x', 's0'), '<f4'), (('y', 's1'), '<f4')])
现在赋值没问题了。
In [105]: a[:,1] = np.array((42,-42), a.dtype)
编辑
In [3]: dt = a.dtype
In [4]: dt
Out[4]: dtype([(('x', 's0'), '<f4'), (('y', 's1'), '<f4')])
使用最近的 recfunctions
添加,我们可以从适当形状的非结构化数组创建结构化数组:
In [5]: import numpy.lib.recfunctions as rf
2d 到 1d 结构化:
In [7]: rf.unstructured_to_structured(np.arange(1,7).reshape(3,2), dtype=dt)
Out[7]:
array([(1., 2.), (3., 4.), (5., 6.)],
dtype=[(('x', 's0'), '<f4'), (('y', 's1'), '<f4')])
3d 到 2d 结构化:
In [8]: rf.unstructured_to_structured(np.arange(24).reshape(4,3,2), dtype=dt)
Out[8]:
array([[( 0., 1.), ( 2., 3.), ( 4., 5.)],
[( 6., 7.), ( 8., 9.), (10., 11.)],
[(12., 13.), (14., 15.), (16., 17.)],
[(18., 19.), (20., 21.), (22., 23.)]],
dtype=[(('x', 's0'), '<f4'), (('y', 's1'), '<f4')])
或者从元组列表创建数组:
In [10]: np.array([(0,1),(2,3)], dt)
Out[10]:
array([(0., 1.), (2., 3.)],
dtype=[(('x', 's0'), '<f4'), (('y', 's1'), '<f4')])
recfunctions
经常使用逐字段设置:
In [16]: for name in a.dtype.names:
...: a[name][:] = np.arange(15).reshape(3,5)
我发现使用结构和 np.ndarrays 使用像 pyopencl.cltypes.float2 这样的 dtypes 非常方便。这是将结构化数据传递到我的内核的一种清晰且自我记录的方式,而不是一堆浮点数。
但是我发现某些行为不方便。例如给定:
import numpy as np
import pyopencl.cltypes as cltp
a = np.zeros((3,5), dtype=cltp.float2)
>>> a
array([[(0., 0.), (0., 0.), (0., 0.), (0., 0.), (0., 0.)],
[(0., 0.), (0., 0.), (0., 0.), (0., 0.), (0., 0.)],
[(0., 0.), (0., 0.), (0., 0.), (0., 0.), (0., 0.)]],
dtype=[(('x', 's0'), '<f4'), (('y', 's1'), '<f4')])
我可以在将数据结构传递给内核之前逐步构建我的数据结构,例如
a[:,1] = (42,-42)
>>> a
array([[( 0., 0.), (42., -42.), ( 0., 0.), ( 0., 0.), ( 0., 0.)],
[( 0., 0.), (42., -42.), ( 0., 0.), ( 0., 0.), ( 0., 0.)],
[( 0., 0.), (42., -42.), ( 0., 0.), ( 0., 0.), ( 0., 0.)]],
dtype=[(('x', 's0'), '<f4'), (('y', 's1'), '<f4')])
这很好。但是我也想将大小为 2 的数组分配给 float2,但这失败了。
a[:,1] = np.array((42,-42))
ValueError: could not broadcast input array from shape (2) into shape (3)
我不得不这样做
a[:,1]['x'] = 42
a[:,1]['y'] = -42
这行得通,但有点违背了整个事情的目的。
我是否遗漏了一些明显的语法差异,或者这个功能不应该以这种方式使用?
编辑: 在我试图展示最简单的例子时,我把问题简单化了。 hpaulj 的回答是正确的,因为如果我在 shape=(2,) 的某些东西上使用显式 dtype=float2,它将转换为 dtype=float2 的 shape=(1,)。 然而,我的实际问题更为笼统,关于如何从 array(shape=(foo, bar, N), dtype=np.float32) 到 array(shape=(foo, bar), dtype=cltp.floatN) N=2,3,4.
刚刚出现的后续问题:是否一定会出现实际副本,还是可以转换'in place'?实际的内存布局乍一看是兼容的。
In [99]: a=np.array([[(0., 0.), (0., 0.), (0., 0.), (0., 0.), (0., 0.)],
...: [(0., 0.), (0., 0.), (0., 0.), (0., 0.), (0., 0.)],
...: [(0., 0.), (0., 0.), (0., 0.), (0., 0.), (0., 0.)]],
...: dtype=[(('x', 's0'), '<f4'), (('y', 's1'), '<f4')])
In [100]: a.dtype
Out[100]: dtype([(('x', 's0'), '<f4'), (('y', 's1'), '<f4')])
In [101]: a.dtype.fields
Out[101]:
mappingproxy({'s0': (dtype('float32'), 0, 'x'),
'x': (dtype('float32'), 0, 'x'),
's1': (dtype('float32'), 4, 'y'),
'y': (dtype('float32'), 4, 'y')})
查看预期目标,一个具有复合数据类型的 3 元素数组:
In [102]: a[:,1]
Out[102]:
array([(0., 0.), (0., 0.), (0., 0.)],
dtype=[(('x', 's0'), '<f4'), (('y', 's1'), '<f4')])
虽然你的数组是 2 元素 int。使用此构造,使用元组不会改变任何内容。
In [103]: np.array((42,-42))
Out[103]: array([ 42, -42])
但是如果我们指定了正确的 dtype,我们将创建一个 0d 数组:
In [104]: np.array((42,-42), a.dtype)
Out[104]: array((42., -42.), dtype=[(('x', 's0'), '<f4'), (('y', 's1'), '<f4')])
现在赋值没问题了。
In [105]: a[:,1] = np.array((42,-42), a.dtype)
编辑
In [3]: dt = a.dtype
In [4]: dt
Out[4]: dtype([(('x', 's0'), '<f4'), (('y', 's1'), '<f4')])
使用最近的 recfunctions
添加,我们可以从适当形状的非结构化数组创建结构化数组:
In [5]: import numpy.lib.recfunctions as rf
2d 到 1d 结构化:
In [7]: rf.unstructured_to_structured(np.arange(1,7).reshape(3,2), dtype=dt)
Out[7]:
array([(1., 2.), (3., 4.), (5., 6.)],
dtype=[(('x', 's0'), '<f4'), (('y', 's1'), '<f4')])
3d 到 2d 结构化:
In [8]: rf.unstructured_to_structured(np.arange(24).reshape(4,3,2), dtype=dt)
Out[8]:
array([[( 0., 1.), ( 2., 3.), ( 4., 5.)],
[( 6., 7.), ( 8., 9.), (10., 11.)],
[(12., 13.), (14., 15.), (16., 17.)],
[(18., 19.), (20., 21.), (22., 23.)]],
dtype=[(('x', 's0'), '<f4'), (('y', 's1'), '<f4')])
或者从元组列表创建数组:
In [10]: np.array([(0,1),(2,3)], dt)
Out[10]:
array([(0., 1.), (2., 3.)],
dtype=[(('x', 's0'), '<f4'), (('y', 's1'), '<f4')])
recfunctions
经常使用逐字段设置:
In [16]: for name in a.dtype.names:
...: a[name][:] = np.arange(15).reshape(3,5)