Python 은 대형 배열 을 어떻게 보 내 고 받 습 니까?

문제.
네트워크 연결 을 통 해 연속 데 이 터 를 보 내 고 받 아들 이 는 대형 배열 을 통 해 데이터 복사 작업 을 최소 화해 야 합 니 다.
해결 방안
다음 함 수 는 memory views 를 이용 하여 큰 배열 을 보 내 고 받 습 니 다.

# zerocopy.py

def send_from(arr, dest):
  view = memoryview(arr).cast('B')
  while len(view):
    nsent = dest.send(view)
    view = view[nsent:]

def recv_into(arr, source):
  view = memoryview(arr).cast('B')
  while len(view):
    nrecv = source.recv_into(view)
    view = view[nrecv:]
테스트 프로그램 을 위해 우선 socket 으로 연 결 된 서버 와 클 라 이언 트 프로그램 을 만 듭 니 다.

>>> from socket import *
>>> s = socket(AF_INET, SOCK_STREAM)
>>> s.bind(('', 25000))
>>> s.listen(1)
>>> c,a = s.accept()
>>>
클 라 이언 트(다른 해석 기 에서):

>>> from socket import *
>>> c = socket(AF_INET, SOCK_STREAM)
>>> c.connect(('localhost', 25000))
>>>
이 절의 목 표 는 연결 을 통 해 초대형 배열 을 전송 하 는 것 이다.이 경우 array 모듈 이나 numpy 모듈 을 통 해 배열 을 만 들 수 있 습 니 다.

# Server
>>> import numpy
>>> a = numpy.arange(0.0, 50000000.0)
>>> send_from(a, c)
>>>

# Client
>>> import numpy
>>> a = numpy.zeros(shape=50000000, dtype=float)
>>> a[0:10]
array([ 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])
>>> recv_into(a, c)
>>> a[0:10]
array([ 0., 1., 2., 3., 4., 5., 6., 7., 8., 9.])
>>>
토론 하 다.
데이터 집약 형 분포 식 계산 과 평행 계산 프로그램 에서 스스로 프로그램 을 써 서 대량의 데 이 터 를 보 내 거나 받 아들 이 는 것 은 흔 하지 않다.그러나 만약 당신 이 확실히 이렇게 하고 싶다 면,낮은 층 의 네트워크 함수 에 사용 할 수 있 도록 데 이 터 를 원본 바이트 로 변환 해 야 할 수도 있 습 니 다.대부분의 네트워크 와 관련 된 함수 가 초대형 데이터 블록 을 한꺼번에 보 내 거나 받 아들 일 수 없 기 때문에 데 이 터 를 여러 블록 으로 절단 해 야 할 수도 있 습 니 다.
하나의 방법 은 특정한 메커니즘 을 사용 하여 데 이 터 를 직렬 화 하 는 것 이다.이 를 바이트 문자열 로 변환 할 수 있다.그러나 이렇게 하면 결국 데이터 의 복 사 를 만 들 수 있다.비록 당신 이 단편 적 으로 이런 일 을 하 더 라 도,당신 의 코드 는 결국 대량의 소형 복사 작업 을 할 것 입 니 다.
이 절 은 메모리 보 기 를 통 해 마법 동작 을 보 여 줍 니 다.본질 적 으로 하나의 메모리 보 기 는 이미 존재 하 는 배열 의 커버 층 이다.뿐만 아니 라 메모리 보 기 는 서로 다른 방식 으로 데 이 터 를 표현 할 수 있 습 니 다.이것 이 바로 아래 문장의 목적 이다.

view = memoryview(arr).cast('B')
이것 은 배열 arr 를 받 아들 여 기호 가 없 는 바이트 의 메모리 보기 로 변환 합 니 다.이 보 기 는 socket 관련 함수,예 를 들 어socket.send() 또는send.recv_into() 에 전 달 될 수 있 습 니 다.내부 에서 이 방법 들 은 이 메모리 영역 을 직접 조작 할 수 있다.예 를 들 어sock.send() 메모리 에서 데 이 터 를 복사 하지 않 고 직접 발생 합 니 다.send.recv_into() 이 메모리 영역 을 작업 을 받 는 입력 버퍼 로 사용 합 니 다.
나머지 어 려 운 점 은 socket 함수 가 일부 데이터 만 조작 할 수 있다 는 것 이다.일반적으로 우 리 는 여러 가지 다른send() recv_into() 을 사용 하여 전체 배열 을 전송 해 야 한다.걱정 하지 마 세 요.작업 할 때마다 보 기 는 바이트 수 를 보 내 거나 받 아들 여 새로운 보기 로 잘 립 니 다.새로운 보기 도 메모리 덮어 쓰기 층 입 니 다.그래서 복사 작업 은 전혀 없다.
문 제 는 수신 자가 얼마나 많은 데 이 터 를 보 내야 하 는 지 미리 알 아야 한 다 는 것 이다.한 배열 을 미리 할당 하거나 받 아들 일 수 있 는 데 이 터 를 이미 존재 하 는 배열 에 넣 을 수 있 도록 해 야 한 다 는 것 이다.알 수 없다 면 발송 자 는 데이터 크기 를 먼저 보 낸 다음 실제 배열 데 이 터 를 보 내야 한다.
이상 은 Python 이 대형 배열 을 어떻게 보 내 고 받 는 지 에 대한 상세 한 내용 입 니 다.Python 이 대형 배열 을 받 는 자 료 를 보 내 는 것 에 대해 서 는 다른 관련 글 을 주목 하 십시오!

좋은 웹페이지 즐겨찾기