0

리눅스와 Windows 시스템에 각각 하나씩 두 개의 Python 3 인터프리터를 실행하고 있습니다. 이들은 multiprocessing.connection (ClientListener)을 사용하여 통신합니다 (즉, 데이터 교환). 이 두 가지 사이에서 ctypes 포인터로 표시된 임의의 데이터 구조의 내용을 동기화 상태로 유지해야합니다.여러 플랫폼에서 ctypes 포인터로 표현 된 메모리 싱크닝 메모리

문제는 데이터의 내용을 효율적으로 앞뒤로 배송해야한다는 것입니다. multiprocessing.connectionpickle 모든 데이터가 제공 될 예정이므로 데이터를 피클 링 할 수있는 데이터로 serialize해야합니다.

지금까지 메모리의 모든 바이트 시퀀스를 파이썬 정수의 파이썬 목록으로 바꿨습니다. 음, (적어도)는 자연적으로 ... 나는 전송해야 할 데이터의 양 측면에서 속도 측면에서 (이보다 효율적으로 만들 수있는 방법이 있는지 궁금

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)[:] 

를 작동).

내가 가진 한 가지 아이디어는 정수 목록 대신 파이썬 바이트 문자열을 사용하여 필요한 메모리 양을 줄이는 것이 었습니다. 그러나, 나는 그것을 작동하게 만들지 못했습니다. 위의 루틴을 어떻게 바꿀 수 있습니까?

그 밖의, 훨씬 더 빠르고/더 빠르고 효율적인 메모리 효율적인 옵션은 무엇입니까? 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'> 
+0

'serialize_pointer_into_int_list'는 picklable이 아닌 ctypes 배열을 반환합니다. –

+0

@MichaelButscher 아마도 C & P 문제일까요? 그것은 나를 위해 작동합니다. 나는'serialize_pointer_into_int_list'의 올바른 사용법을 보여주는 예제를 질문에 추가했습니다. –

+0

필자는 끝에 ctypes 배열을리스트로 변환하는'[:]'을 마지막으로 살펴 보았습니다. –

답변

1

가 될 수있다 이 방법 (대화 형 셸에 표시됨) :

>>> 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] 
+0

'b'에서'bytes'를 실행하는 것은 정말 멋진 아이디어입니다, 감사합니다. 나는 이것이 ctypes 객체에서 가능하다는 것을 몰랐다. 내가 볼 수없는 것은 비록 당신의 예제 (알려진 타입의 고정 된 길이의 배열)와 같이 "명백한"것이 아니라면 메모리 세그먼트의 길이를 고려할 수있는 방법이다. 내'serialize_pointer' 루틴은 의도적으로이 목적을위한'size_bytes' 매개 변수를 가지고 있습니다 ('bytes' 루틴은 그런 매개 변수를 가지고 있지 않습니다). 결국 포인터가 가리키는 데이터 유형에 관계없이 모든 유형의 포인터를 허용하기를 원합니다. –

+0

@ s-m-e'bytes' 객체의 바이트 수는 일반적인'len (c) '를 사용하여 검색 할 수 있습니다. –