代码之家  ›  专栏  ›  技术社区  ›  s-m-e

在多个平台上跨python进程同步由ctypes指针表示的内存

  •  0
  • s-m-e  · 技术社区  · 6 年前

    我正在运行两个Python 3解释器,一个在Linux上,一个在Windows系统上。他们使用 multiprocessing.connection Client Listener ). 在这两者之间,我必须保留由表示的任意数据结构的内容 ctypes 指针同步。

    问题是我需要高效地来回传送数据的内容。 多处理。联系 pickle 所以我必须将数据序列化为可以pickle的内容。

    到目前为止,我将内存中的每个字节序列转换为Python整数的Python列表。嗯,它(至少)起作用了。。。

    def generate_pointer_from_int_list(int_array):
    
        return ctypes.pointer((ctypes.c_ubyte * len(int_array))(*int_array))
    
    
    def overwrite_pointer_with_int_list(ctypes_pointer, int_array):
    
        (ctypes.c_ubyte * len(int_array)).from_address(ctypes.c_void_p.from_buffer(ctypes_pointer).value)[:] = int_array[:]
    
    
    def serialize_pointer_into_int_list(ctypes_pointer, size_bytes):
    
        return (ctypes.c_ubyte * size_bytes).from_address(ctypes.c_void_p.from_buffer(ctypes_pointer).value)[:]
    

    我想知道是否有方法可以提高效率(当然是在需要传输的数据量和速度方面)。

    我的一个想法是使用Python字节字符串而不是整数列表,这将减少所需的内存量。然而,我没有设法使它工作。我该如何改变上述常规呢?

    我还有什么其他可能更好/更快/更节省内存的选项?


    的使用示例 serialize_pointer_into_int_list :

    sample_len = 5
    sample_p = ctypes.pointer((ctypes.c_double * sample_len)(1.0, 2.0, 3.0, 4.0, 5.0))
    sample_int_list = serialize_pointer_into_int_list(sample_p, sample_len * ctypes.sizeof(ctypes.c_double))
    print(sample_int_list)
    print(type(sample_int_list))
    

    输出:

    [0, 0, 0, 0, 0, 0, 240, 63, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 8, 64, 0, 0, 0, 0, 0, 0, 16, 64, 0, 0, 0, 0, 0, 0, 20, 64]
    <class 'list'>
    
    1 回复  |  直到 6 年前
        1
  •  1
  •   Michael Butscher    6 年前

    假设每个数据部分都没有那么大(因为复制对于解决方案来说是必要的),可以这样做(如interactive shell中所示):

    >>> import pickle
    >>> import ctypes
    >>> b = (ctypes.c_double * 5)(1.0, 2.0, 3.0, 4.0, 5.0)  # Arbitrary data
    >>> d = pickle.dumps(bytes(b))
    >>> c = pickle.loads(d)
    >>> a = (ctypes.c_double * 5).from_buffer_copy(c)
    >>> a
    <__main__.c_double_Array_5 object at 0x02F6C9E0>
    >>> list(a)
    [1.0, 2.0, 3.0, 4.0, 5.0]