복붙노트

[PYTHON] 마샬링 덤프가 더 빨라지고 cPickle이 더 빨리로드됩니다.

PYTHON

마샬링 덤프가 더 빨라지고 cPickle이 더 빨리로드됩니다.

대형 객체를 직렬화 및 비 직렬화해야하는 프로그램을 구현하고 있으므로 pickle, cPickle 및 marshal 모듈을 사용하여 몇 가지 테스트를 수행하여 최상의 모듈을 선택했습니다. 길을 끼고 나는 매우 흥미있는 무엇인가 발견했다 :

나는 덤프를 사용하고 dicts, tuples, ints, float 및 strings 목록에 각 모듈에 대해로드하고있다.

이것은 내 벤치 마크 결과입니다.

DUMPING a list of length 7340032
----------------------------------------------------------------------
pickle => 14.675 seconds
length of pickle serialized string: 31457430

cPickle => 2.619 seconds
length of cPickle serialized string: 31457457

marshal => 0.991 seconds
length of marshal serialized string: 117440540

LOADING a list of length: 7340032
----------------------------------------------------------------------
pickle => 13.768 seconds
(same length?) 7340032 == 7340032

cPickle => 2.038 seconds
(same length?) 7340032 == 7340032

marshal => 6.378 seconds
(same length?) 7340032 == 7340032

따라서 이러한 결과로부터 우리는 육군 원수가 벤치 마크의 투기 부분에서 매우 빠르다는 것을 알 수 있습니다 :

그러나 놀랍게도 육분은 로딩 부분에서 cPickle보다 훨씬 느립니다.

RAM의 경우에도로드하는 동안 마샬링 성능이 매우 비효율적이었습니다.

marshal을 사용하는 로딩이 왜 그렇게 느린지는 필자의 직렬화 된 문자열 (pickle과 cPickle보다 훨씬 길다)의 길이와 어떻게 관련이 있는지 추측하고있다.

해결법

  1. ==============================

    1.cPickle은 마샬링 (marshal)보다 더 똑똑한 알고리즘을 가지고 있으며 대형 객체가 사용하는 공간을 줄이기 위해 트릭을 수행 할 수 있습니다. 즉, 디코딩 속도가 느려지지만 결과 출력이 작을수록 인코딩 속도가 빠릅니다. 마샬링은 단순하고 객체를 더 이상 분석하지 않고 그대로 직렬화합니다. 또한 마샬링로드가 왜 비효율적인지에 대한 해답을 제시합니다. 디스크에서 더 많은 데이터를 읽는 것처럼 cPickle과 동일한 작업을 수행하기 만하면됩니다.

    cPickle은 마샬링 (marshal)보다 더 똑똑한 알고리즘을 가지고 있으며 대형 객체가 사용하는 공간을 줄이기 위해 트릭을 수행 할 수 있습니다. 즉, 디코딩 속도가 느려지지만 결과 출력이 작을수록 인코딩 속도가 빠릅니다. 마샬링은 단순하고 객체를 더 이상 분석하지 않고 그대로 직렬화합니다. 또한 마샬링로드가 왜 비효율적인지에 대한 해답을 제시합니다. 디스크에서 더 많은 데이터를 읽는 것처럼 cPickle과 동일한 작업을 수행하기 만하면됩니다.

    marshal 및 cPickle은 결국 실제로는 다른 것입니다. 빠른 저장은 디스크에 많은 데이터를 저장한다는 것을 의미하는 데이터 구조를 분석하는 것을 의미하므로 실제로는 빠른 저장과 빠른로드를 모두 얻을 수 없습니다.

    마샬링 (marshal)이 다른 버전의 파이썬과 호환되지 않을 수도 있다는 사실에 관해서는 일반적으로 cPickle을 사용해야합니다.

  2. ==============================

    2.어떤 사람들은 이것을 너무 많은 해킹으로 생각할 수도 있지만 단순히 피클 덤프 호출을 gc.disable () 및 gc.enable ()로 래핑하면 큰 성공을 거두었습니다. 예를 들어, ~ 50MB의 사전 목록을 작성하는 아래의 저널은 78 초에서 4 초가됩니다.

    어떤 사람들은 이것을 너무 많은 해킹으로 생각할 수도 있지만 단순히 피클 덤프 호출을 gc.disable () 및 gc.enable ()로 래핑하면 큰 성공을 거두었습니다. 예를 들어, ~ 50MB의 사전 목록을 작성하는 아래의 저널은 78 초에서 4 초가됩니다.

    #  not a complete example....
    gc.disable()
    cPickle.dump(params,fout,cPickle.HIGHEST_PROTOCOL)         
    fout.close()               
    gc.enable()
    
  3. ==============================

    3.이러한 벤치 마크의 차이점은 cPickle의 속도 향상에 대한 하나의 아이디어를 제공합니다.

    이러한 벤치 마크의 차이점은 cPickle의 속도 향상에 대한 하나의 아이디어를 제공합니다.

    Input: ["This is a string of 33 characters" for _ in xrange(1000000)]
    cPickle dumps 0.199 s loads 0.099 s 2002041 bytes
    marshal dumps 0.368 s loads 0.138 s 38000005 bytes
    
    Input: ["This is a string of 33 "+"characters" for _ in xrange(1000000)]
    cPickle dumps 1.374 s loads 0.550 s 40001244 bytes
    marshal dumps 0.361 s loads 0.141 s 38000005 bytes
    

    첫 번째 경우 목록은 동일한 문자열을 반복합니다. 두 번째 목록은 동일하지만 표현식의 결과이므로 각 문자열은 별도의 객체입니다. 이제 원래 외부 소스에서 데이터를 읽는 경우 일종의 문자열 중복 제거를 고려할 수 있습니다.

  4. ==============================

    4.cPickle cca를 만들 수 있습니다. cPickle.Pickler의 인스턴스를 만들고 문서화되지 않은 옵션 인 'fast'를 1로 설정하여 50 배속 (!)

    cPickle cca를 만들 수 있습니다. cPickle.Pickler의 인스턴스를 만들고 문서화되지 않은 옵션 인 'fast'를 1로 설정하여 50 배속 (!)

    outfile = open('outfile.pickle')
    fastPickler = cPickle.Pickler(outfile, cPickle.HIGHEST_PROTOCOL)
    fastPickler.fast = 1
    fastPickler.dump(myHugeObject)
    outfile.close()
    

    그러나 myHugeObject에 순환 참조가있는 경우 덤프 메소드는 절대로 종료되지 않습니다.

  5. ==============================

    5.보시다시피, cPickle.dump가 생성하는 출력에는 marshal.dump가 생성하는 출력의 약 1/4이 있습니다. 즉, cPickle은 불필요한 것들이 제거 될 때 데이터를 덤프하는 더 복잡한 알고리즘을 사용해야합니다. 덤프 된 목록을로드 할 때 마샬은 더 많은 데이터를 처리해야하지만 분석해야하는 데이터가 적기 때문에 cPickle은 데이터를 빠르게 처리 할 수 ​​있습니다.

    보시다시피, cPickle.dump가 생성하는 출력에는 marshal.dump가 생성하는 출력의 약 1/4이 있습니다. 즉, cPickle은 불필요한 것들이 제거 될 때 데이터를 덤프하는 더 복잡한 알고리즘을 사용해야합니다. 덤프 된 목록을로드 할 때 마샬은 더 많은 데이터를 처리해야하지만 분석해야하는 데이터가 적기 때문에 cPickle은 데이터를 빠르게 처리 할 수 ​​있습니다.

    마샬링 (marshal)이 다른 버전의 파이썬과 호환되지 않을 수도 있다는 사실에 관해서는 일반적으로 cPickle을 사용해야합니다.

  6. ==============================

    6.직렬화 결과를 압축하여 저장 효율성을 향상시킬 수 있습니다.

    직렬화 결과를 압축하여 저장 효율성을 향상시킬 수 있습니다.

    나의 직감은 데이터를 압축하고 그것을 unserialize에 공급하는 것이 HDD를 통해 디스크에서 원시를 읽는 것보다 빠를 것이라고합니다.

    아래의 테스트는 압축이 unserialize 프로세스의 속도를 향상 시킨다는 것을 증명하기 위해 만들어졌습니다. 기계가 SSD를 장비했기 때문에 그 결과는 기대와 달랐습니다. HZD 장비에서는 lz4를 사용하여 데이터를 압축하는 것이 평균 60-70mb / s의 디스크 읽기 때문에 빠릅니다.

    LZ4 : 18 %의 속도 감소에서 압축은 추가 저장 용량의 77.6 %를 산출합니다.

    marshal - compression speed time
    Bz2 7.492605924606323  10363490
    Lz4 1.3733329772949219 46018121
    --- 1.126852035522461 205618472
    cPickle - compression speed time
    Bz2 15.488649845123291 10650522
    Lz4 9.192650079727173  55388264
    --- 8.839831113815308 204340701
    
  7. from https://stackoverflow.com/questions/8514020/marshal-dumps-faster-cpickle-loads-faster by cc-by-sa and MIT license