공유 메모리.음반에 오르다

15872 단어 Pythontech

TL; DR

  • 파이톤 3.7 지원
  • 머신러닝에 사용되는 16비트 부동 소수점 지원np.float16
  • from multiprocessing.sharedctypes import RawArray
    import numpy as np
    
    # 載せたい型とサイズの指定
    dtype = np.float16
    shape = (3,2)
    
    # ここから
    try:
        ctype = np.ctypeslib.as_ctypes_type(np.dtype(dtype))
    except NotImplementedError:
        for d in (np.int8, np.int16, np.int32, np.int64):
            _d = np.dtype(d)
    	if np.dtype(dtype).itemsize == _d.itemsize:
    	    ctype = np.ctypeslib.as_ctypes_type(_d)
    	    break
        else:
            raise
    
    len = int(np.array(shape, copy=False,dtype="int").prod())
    data = np.ctypeslib.as_array(RawArray(ctype, len))
    data.shape = shape
    array = data.view(dtype)
    

    동력


    개인이 개발한학습을 위한 Experience Replay 라이브러리 강화에서는 다중 프로세스에 대응하기 위해numpy.ndarray 데이터를 공유 메모리에 구성하려고 한다.
    https://zenn.dev/ymd_h/articles/03edcaa47a3b1c

    1. 공유 메모리 만드는 법


    파이썬 3.8 이후 표준 라이브러리에 바이트 수multiprocessing.shared_memory를 직접 지정할 수 있지만 파이썬 3.7에서는 사용할 수 없습니다.
    https://docs.python.org/ja/3/library/multiprocessing.shared_memory.html
    파이썬 3.7에서 사용 가능multiprocessing.sharedctypes.RawArray.
    이것은 ctypes에 정의된 "C 호환 형식 또는 문자 형식 코드"와 "기본 소수"로 지정해야 한다
    https://docs.python.org/ja/3/library/multiprocessing.html#multiprocessing.sharedctypes.RawArray

    2. np.ctypeslib 사용

    numpy.dtype에서 ctypes로 바꿀 수 있는 함수 그룹numpy.ctypeslib.
    https://qiita.com/maiueo/items/b3021a8803859d35a46f
    https://numpy.org/doc/stable/reference/routines.ctypeslib.html
    나는 이렇게 하면 완성될 줄 알았다.
    from multiprocessing.sharedctypes import RawArray
    import numpy as np
    
    # 載せたい型とサイズの指定
    dtype = np.single
    shape = (3,2)
    
    # ここから
    ctype = np.ctypeslib.as_ctypes_type(np.dtype(dtype))
    len = int(np.array(shape, copy=False,dtype="int").prod())
    data = np.ctypeslib.as_array(RawArray(ctype, len))
    data.shape = shape # reshape を使うとコピーしうるので、attribute に直代入
    

    3. C 비호환성에 대한 대응


    완성된 줄 알았는데 사용자가isseue 보고서를 왔어요."np.float16"에서 오류가 발생한 경우
    https://gitlab.com/ymd_h/cpprb/-/issues/130 NotImplementedError: Converting dtype('float16') to a ctypes type16비트 부동점은 최근 64비트 환경에서 C 언어와 호환되지 않으므로 오류로 변환할 수 없습니다.
    머신러닝에서는 정밀도를 희생해 데이터 크기를 줄이는 경우도 많은데np.float16 대응하지 않으면 좋지 않아 대책을 강구했다.
    변환ctypes을 거치지 않고 같은 바이트의 공유 메모리를 강제로 다시 읽는 방법을 채택했다.daray의reintepret는 view()에서 지정할 수 있다dtype.
    https://stackoverflow.com/questions/22623135/converting-from-numpy-array-of-one-type-to-another-by-re-interpreting-raw-bytes ctypes로 변환할 수 없을 때 변수의 크기가 8비트, 16비트, 32비트, 64비트인지 확인하고 해당하는 유형으로 공유 메모리를 만듭니다.(128비트는 환경 종속성이므로 지원되지 않음)
    try:
        ctype = np.ctypeslib.as_ctypes_type(np.dtype(dtype))
    except NotImplementedError:
        for d in (np.int8, np.int16, np.int32, np.int64):
            _d = np.dtype(d)
    	if np.dtype(dtype).itemsize == _d.itemsize:
                ctype = np.ctypeslib.as_ctypes_type(_d)
                break
        else:
            # どれにもマッチしなければ、再度 NotImplementedError を上げる
            raise
    
    은 아예 전체np.byte의 배수로 저장기를 확보할 수 있지만, np.byte의 크기도 환경의존성 1byte에 국한되지 않기 때문에 가능한 설치된as_ctypes_type에 의뢰해 주울 수 없는 부분에 개별적으로 대응할 예정이다.

    완성판(재판)


    from multiprocessing.sharedctypes import RawArray
    import numpy as np
    
    # 載せたい型とサイズの指定
    dtype = np.float16
    shape = (3,2)
    
    # ここから
    try:
        ctype = np.ctypeslib.as_ctypes_type(np.dtype(dtype))
    except NotImplementedError:
        for d in (np.int8, np.int16, np.int32, np.int64):
            _d = np.dtype(d)
    	if np.dtype(dtype).itemsize == _d.itemsize:
    	    ctype = np.ctypeslib.as_ctypes_type(_d)
    	    break
        else:
            raise
    
    len = int(np.array(shape, copy=False,dtype="int").prod())
    data = np.ctypeslib.as_array(RawArray(ctype, len))
    data.shape = shape
    array = data.view(dtype)
    

    좋은 웹페이지 즐겨찾기