Numpy Memmap Ctypes 访问
Numpy Memmap Ctypes Access
我正在尝试通过 numpy memmap 使用一个非常大的 numpy 数组,将每个元素作为 ctypes 结构进行访问。
class My_Structure(Structure):
_fields_ = [('field1', c_uint32, 3),
('field2', c_uint32, 2),
('field3', c_uint32, 2),
('field4', c_uint32, 9),
('field5', c_uint32, 12),
('field6', c_uint32, 2),
('field7', c_uint32, 2)]
def __str__(self):
return f'MyStruct -- f1{self.field1} f2{self.field2} f3{self.field3} f3{self.field4} f5{self.field5} f6{self.field6} f7{self.field7}'
def __eq__(self, other):
for field in self._fields_:
if getattr(self, field[0]) != getattr(other, field[0]):
return False
return True
_big_array = np.memmap(filename = 'big_file.data',
dtype = 'uint32',
mode = 'w+',
shape = 1000000
)
big_array = _big_array.ctypes.data_as(ctypes.POINTER(My_Structure))
big_array[0].field1 = 5
...
它似乎工作正常,但我在 64 位 Windows 机器上遇到错误,python.exe 只是停止。在事件查看器中,我看到故障模块名称是 _ctypes.pyd
,异常代码是 0xc0000005,我认为这是一个访问异常。
我似乎没有在 Linux 上遇到同样的错误,尽管我的测试还不够彻底。
我的问题是:
我的访问看起来正确吗? IE。我使用 numpy.memmap.ctypes.data_as
正确吗?
我在 My_Structure
上定义了函数(__str__
和 __eq__
)是否改变了它的大小? IE。它仍然可以在数组中用作 uint32
?
您认为有什么可能导致此行为的吗?特别是考虑到 Windows 和 Linux?
之间的差异
编辑:
在 big_array 元素上使用 ctypes.addressof
和 ctypes.sizeof
,看起来 __str__
和 __eq__
不会影响大小共 My_Structure
我在访问big_array
之前添加了一些断言,发现我正在尝试访问big_array[-1]
,这解释了访问错误和崩溃。
这让问题 1 悬而未决:看起来我的代码在技术上是正确的,但我想知道是否有比使用 ctypes.pointer 更好的方法来访问 numpy 数组,这样我仍然可以得到使用 numpy 数组的好处(越界访问警告、负索引环绕等)。下面的 Daniel 建议使用结构化的 numpy 数组,但是可以用它来进行位域访问吗?
您可以在最后一步转换为 ctypes
,而不是第一步:
_big_array[0, ...].ctypes.data_as(ctypes.POINTER(My_Structure)).field1 = 5
请注意,需要 ...
来将结果保留为 0d 数组,以便存在 .ctypes
属性
当然,负索引也可以正常工作:
_big_array[-1, ...].ctypes.data_as(ctypes.POINTER(My_Structure)).field1 = 5
Daniel below suggested using a structured numpy array, but is it possible to do bitfield access with this?
没有
我正在尝试通过 numpy memmap 使用一个非常大的 numpy 数组,将每个元素作为 ctypes 结构进行访问。
class My_Structure(Structure):
_fields_ = [('field1', c_uint32, 3),
('field2', c_uint32, 2),
('field3', c_uint32, 2),
('field4', c_uint32, 9),
('field5', c_uint32, 12),
('field6', c_uint32, 2),
('field7', c_uint32, 2)]
def __str__(self):
return f'MyStruct -- f1{self.field1} f2{self.field2} f3{self.field3} f3{self.field4} f5{self.field5} f6{self.field6} f7{self.field7}'
def __eq__(self, other):
for field in self._fields_:
if getattr(self, field[0]) != getattr(other, field[0]):
return False
return True
_big_array = np.memmap(filename = 'big_file.data',
dtype = 'uint32',
mode = 'w+',
shape = 1000000
)
big_array = _big_array.ctypes.data_as(ctypes.POINTER(My_Structure))
big_array[0].field1 = 5
...
它似乎工作正常,但我在 64 位 Windows 机器上遇到错误,python.exe 只是停止。在事件查看器中,我看到故障模块名称是 _ctypes.pyd
,异常代码是 0xc0000005,我认为这是一个访问异常。
我似乎没有在 Linux 上遇到同样的错误,尽管我的测试还不够彻底。
我的问题是:
我的访问看起来正确吗? IE。我使用
numpy.memmap.ctypes.data_as
正确吗?我在
My_Structure
上定义了函数(__str__
和__eq__
)是否改变了它的大小? IE。它仍然可以在数组中用作uint32
?您认为有什么可能导致此行为的吗?特别是考虑到 Windows 和 Linux?
之间的差异
编辑:
在 big_array 元素上使用
ctypes.addressof
和ctypes.sizeof
,看起来__str__
和__eq__
不会影响大小共My_Structure
我在访问
big_array
之前添加了一些断言,发现我正在尝试访问big_array[-1]
,这解释了访问错误和崩溃。
这让问题 1 悬而未决:看起来我的代码在技术上是正确的,但我想知道是否有比使用 ctypes.pointer 更好的方法来访问 numpy 数组,这样我仍然可以得到使用 numpy 数组的好处(越界访问警告、负索引环绕等)。下面的 Daniel 建议使用结构化的 numpy 数组,但是可以用它来进行位域访问吗?
您可以在最后一步转换为 ctypes
,而不是第一步:
_big_array[0, ...].ctypes.data_as(ctypes.POINTER(My_Structure)).field1 = 5
请注意,需要 ...
来将结果保留为 0d 数组,以便存在 .ctypes
属性
当然,负索引也可以正常工作:
_big_array[-1, ...].ctypes.data_as(ctypes.POINTER(My_Structure)).field1 = 5
Daniel below suggested using a structured numpy array, but is it possible to do bitfield access with this?
没有