为numpy.frombuffer
函数的文档具体说,所产生的阵列将是一维:如何从多维缓冲区初始化一个NumPy数组?
解释一个缓冲区作为1维阵列。
我不确定此报价的后果。文档只是告诉我,生成的数组将是一维的,但从不说输入缓冲区必须描述一维对象。
我在C++中有一个(2D)Eigen matrix。我想创建一个Python buffer,它描述矩阵的内容。然后,我想用这个缓冲区来初始化我的NumPy数组,并将它提供给我的Python脚本。目标是将信息传递给Python而不复制数据并允许python修改矩阵(例如初始化矩阵)。
的numpy.frombuffer
的C-API当量PyArray_FromBuffer
,并且它也共享单维短语,但它有更多的文档(重点煤矿):
PyObject* PyArray_FromBuffer(PyObject* buf, PyArray_Descr* dtype, npy_intp count, npy_intp offset)
构建的一维从导出缓冲区协议(或具有返回导出缓冲区协议的对象的属性__buffer__)的对象buf导出单个类型的ndarray。首先会尝试写入缓冲区,然后再尝试读取缓冲区。返回数组的NPY_ARRAY_WRITEABLE标志将反映哪一个成功。假定数据从对象的内存位置开始的偏移量字节处开始。缓冲区中数据的类型将根据数据类型描述符dtype进行解释。如果count为负,那么它将根据缓冲区的大小和请求的itemsize来确定,否则,count表示应该从缓冲区转换多少个元素。
“单段”是指它不能包含使用的填充,例如对齐矩阵的行吗?在这种情况下,我搞砸了,因为我的矩阵可以很好地使用需要填充的对齐策略。
回到原来的问题:
有我的方式来创建一个与NumPy阵列,其与预先存在的缓冲共享内存?
备注:有在GitHub上的一个项目叫Eigen3ToPython,其目的是与蟒蛇连接征,但它并不支持内存共享(重点煤矿):
(然而, 内存不是两种表示之间共享)这个库允许:[...]从numpy的阵列(
np.array
)以透明的方式转换为/
编辑 有人可能会指出了同样的同名问题Numpy 2D- Array from Buffer?。不幸的是,这里给出的解决方案似乎不适合我的情况,因为生成的二维数组不会与原始缓冲区共享内存。
编辑:如何在数据本征
征2D矩阵映射在一维缓冲存储器,通过使用跨距访问组织的。例如,双精度3×2矩阵需要6倍,即48个字节。一个48字节的缓冲区被分配。此缓冲区中的第一个元素表示矩阵中的[0, 0]
条目。
为了访问该元素[i, j]
,下面的公式:
double* v = matrix.data() + i*matrix.rowStride() + j*matrix.colStride()
,其中matrix
是矩阵对象和它的成员函数data()
,rowStride()
和colStride()
返回分别的起始地址缓冲区,两个连续行之间的距离以及两个连续列之间的距离(浮点格式大小的倍数)。
默认情况下,Eigen使用列主要格式,因此rowStride() == 1
,但它也可以配置为使用行主格式,并使用colStride() == 1
。
另一个重要的配置选项是对齐。数据缓冲区很可能包含一些不需要的值(即,不是矩阵的一部分的值),以使列或行开始于对齐的地址。这使得矩阵上的操作可以进行矢量化。在上面的例子中,假设列优先格式和16字节对齐,下面的矩阵
3 7
1 -2
4 5
可以存储赢取以下缓冲液:
0 0 3 1 4 0 7 -2 5 0
的0值被称为填充。开始处的两个0可能是必要的,以确保实际数据的开始对齐到相同的边界。 (请注意,data()
成员函数将返回3的地址)。在这种情况下,为步幅的行和列是
rowStride: 1
colStride: 4
(而在未对齐的情况下,它们将是1和3分别。)
Numpy需要一个C连续缓冲区,即没有填充的行主结构。如果Eigen没有插入填充,那么可以非常容易地解决列主要特征矩阵的行主要问题的问题:将缓冲区传递给一个numpy数组,然后重构和转置结果ndarray
。我设法完美地完成了这项工作。
但是在Eigen插入填充的情况下,使用这种技术无法解决问题,因为ndarray
仍然会看到数据中的零,并认为它们是矩阵的一部分,同时丢弃了某些值数组的末尾。而这是我问一个解决方案的问题。
现在,作为一个方面的评论,既然我们在循环中有@ggael的运气,谁可能会说出一些光,我不得不承认,我从来没有Eigen在我的矩阵中插入任何填充。我在Eigen文档中似乎没有发现任何填充。但是,我希望对齐策略能够对齐每一列(或行),而不仅仅是第一列。我的期望错了吗?如果我是,那么整个问题不适用于Eigen。但是它适用于我正在使用的其他图书馆,这些图书馆采用了上述的校准策略,所以请在回答问题时不要考虑最后一段。
您是否尝试过直接使用['np。]创建NumPy数组。ndarray'](https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.ndarray.html)?根据文档,它有一个'buffer'参数。 – unutbu
'numpy'数据存储在一个平面缓冲区中。所以一个缓冲区(一组连续的字节)包含4000个字节,我们指定dtype'int32','frombuffer'应该给一个(1000)形状的数组。随后的“重塑”可以使其成为2D。在numpy多维度是由形状和步幅属性,而不是数据。 – hpaulj
解释'Eigen'如何存储其数据。它是一个简单的1d缓冲区吗?或者更像是指向指针的“C”指针? – hpaulj