복붙노트

[PYTHON] Python에서 피클 파일을로드하는 데 걸리는 시간을 줄이는 방법

PYTHON

Python에서 피클 파일을로드하는 데 걸리는 시간을 줄이는 방법

파이썬으로 사전을 만들고 피클에 버렸습니다. 그것의 크기는 300MB에 갔다. 이제, 같은 피클을 적재하고 싶습니다.

output = open('myfile.pkl', 'rb')
mydict = pickle.load(output)

이 피클을 적재하는 데 약 15 초가 걸립니다. 이 시간을 어떻게 줄일 수 있습니까?

하드웨어 사양 : Ubuntu 14.04, 4GB RAM

아래 코드는 json, pickle, cPickle을 사용하여 파일을 덤프하거나로드하는 데 걸리는 시간을 보여줍니다.

덤핑 후 파일 크기는 약 300MB가됩니다.

import json, pickle, cPickle
import os, timeit
import json

mydict= {all values to be added}

def dump_json():    
    output = open('myfile1.json', 'wb')
    json.dump(mydict, output)
    output.close()    

def dump_pickle():    
    output = open('myfile2.pkl', 'wb')
    pickle.dump(mydict, output,protocol=cPickle.HIGHEST_PROTOCOL)
    output.close()

def dump_cpickle():    
    output = open('myfile3.pkl', 'wb')
    cPickle.dump(mydict, output,protocol=cPickle.HIGHEST_PROTOCOL)
    output.close()

def load_json():
    output = open('myfile1.json', 'rb')
    mydict = json.load(output)
    output.close()

def load_pickle():
    output = open('myfile2.pkl', 'rb')
    mydict = pickle.load(output)
    output.close()

def load_cpickle():
    output = open('myfile3.pkl', 'rb')
    mydict = pickle.load(output)
    output.close()


if __name__ == '__main__':
    print "Json dump: "
    t = timeit.Timer(stmt="pickle_wr.dump_json()", setup="import pickle_wr")  
    print t.timeit(1),'\n'

    print "Pickle dump: "
    t = timeit.Timer(stmt="pickle_wr.dump_pickle()", setup="import pickle_wr")  
    print t.timeit(1),'\n'

    print "cPickle dump: "
    t = timeit.Timer(stmt="pickle_wr.dump_cpickle()", setup="import pickle_wr")  
    print t.timeit(1),'\n'

    print "Json load: "
    t = timeit.Timer(stmt="pickle_wr.load_json()", setup="import pickle_wr")  
    print t.timeit(1),'\n'

    print "pickle load: "
    t = timeit.Timer(stmt="pickle_wr.load_pickle()", setup="import pickle_wr")  
    print t.timeit(1),'\n'

    print "cPickle load: "
    t = timeit.Timer(stmt="pickle_wr.load_cpickle()", setup="import pickle_wr")  
    print t.timeit(1),'\n'

출력 :

Json dump: 
42.5809804916 

Pickle dump: 
52.87407804489 

cPickle dump: 
1.1903790187836 

Json load: 
12.240660209656 

pickle load: 
24.48748306274 

cPickle load: 
24.4888298893

나는 cPickle이 덤프하고로드하는데 더 적은 시간이 걸리는 것을 보았지만 파일 로딩은 여전히 ​​오랜 시간이 걸린다.

해결법

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

    1.피클 대신 json 라이브러리를 사용해보십시오. 비교적 단순한 사전 인 사전을 다루기 때문에이 옵션을 선택해야합니다.

    피클 대신 json 라이브러리를 사용해보십시오. 비교적 단순한 사전 인 사전을 다루기 때문에이 옵션을 선택해야합니다.

    이 웹 사이트에 따르면,

    또한 더 빠른 것은 무엇입니까? 절편 사전 객체로드 또는 JSON 파일로드 사전에 대한 질문입니다.

    파이썬을 업그레이드하거나 파이썬 버전이 고정 된 마샬 모듈을 사용하면 속도를 향상시키는 데 도움이됩니다 (여기에서 수정 한 코드).

    try: import cPickle
    except: import pickle as cPickle
    import pickle
    import json, marshal, random
    from time import time
    from hashlib import md5
    
    test_runs = 1000
    
    if __name__ == "__main__":
        payload = {
            "float": [(random.randrange(0, 99) + random.random()) for i in range(1000)],
            "int": [random.randrange(0, 9999) for i in range(1000)],
            "str": [md5(str(random.random()).encode('utf8')).hexdigest() for i in range(1000)]
        }
        modules = [json, pickle, cPickle, marshal]
    
        for payload_type in payload:
            data = payload[payload_type]
            for module in modules:
                start = time()
                if module.__name__ in ['pickle', 'cPickle']:
                    for i in range(test_runs): serialized = module.dumps(data, protocol=-1)
                else:
                    for i in range(test_runs): serialized = module.dumps(data)
                w = time() - start
                start = time()
                for i in range(test_runs):
                    unserialized = module.loads(serialized)
                r = time() - start
                print("%s %s W %.3f R %.3f" % (module.__name__, payload_type, w, r))
    

    결과 :

    C:\Python27\python.exe -u "serialization_benchmark.py"
    json int W 0.125 R 0.156
    pickle int W 2.808 R 1.139
    cPickle int W 0.047 R 0.046
    marshal int W 0.016 R 0.031
    json float W 1.981 R 0.624
    pickle float W 2.607 R 1.092
    cPickle float W 0.063 R 0.062
    marshal float W 0.047 R 0.031
    json str W 0.172 R 0.437
    pickle str W 5.149 R 2.309
    cPickle str W 0.281 R 0.156
    marshal str W 0.109 R 0.047
    
    C:\pypy-1.6\pypy-c -u "serialization_benchmark.py"
    json int W 0.515 R 0.452
    pickle int W 0.546 R 0.219
    cPickle int W 0.577 R 0.171
    marshal int W 0.032 R 0.031
    json float W 2.390 R 1.341
    pickle float W 0.656 R 0.436
    cPickle float W 0.593 R 0.406
    marshal float W 0.327 R 0.203
    json str W 1.141 R 1.186
    pickle str W 0.702 R 0.546
    cPickle str W 0.828 R 0.562
    marshal str W 0.265 R 0.078
    
    c:\Python34\python -u "serialization_benchmark.py"
    json int W 0.203 R 0.140
    pickle int W 0.047 R 0.062
    pickle int W 0.031 R 0.062
    marshal int W 0.031 R 0.047
    json float W 1.935 R 0.749
    pickle float W 0.047 R 0.062
    pickle float W 0.047 R 0.062
    marshal float W 0.047 R 0.047
    json str W 0.281 R 0.187
    pickle str W 0.125 R 0.140
    pickle str W 0.125 R 0.140
    marshal str W 0.094 R 0.078
    

    Python 3.4는 기본값으로 pickle 프로토콜 3을 사용합니다. 프로토콜 4와 비교하면 차이가 없습니다. Python 2는 프로토콜 2보다 프로토콜 2가 가장 높고 (덤프에 음수 값이 제공되면 선택됨) 프로토콜 2를 사용합니다.

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

    2.cPickle 자체를 사용하여 거대한 파일 (예 : ~ 750 MB igraph 객체 - 바이너리 피클 파일)을 읽는 데 좋은 결과를 얻었습니다. 이것은 여기에 언급 된 피클로드 콜을 간단하게 마무리함으로써 달성되었습니다.

    cPickle 자체를 사용하여 거대한 파일 (예 : ~ 750 MB igraph 객체 - 바이너리 피클 파일)을 읽는 데 좋은 결과를 얻었습니다. 이것은 여기에 언급 된 피클로드 콜을 간단하게 마무리함으로써 달성되었습니다.

    귀하의 경우 스 니펫 예제는 다음과 같습니다.

    import timeit
    import cPickle as pickle
    import gc
    
    
    def load_cpickle_gc():
        output = open('myfile3.pkl', 'rb')
    
        # disable garbage collector
        gc.disable()
    
        mydict = pickle.load(output)
    
        # enable garbage collector again
        gc.enable()
        output.close()
    
    
    if __name__ == '__main__':
        print "cPickle load (with gc workaround): "
        t = timeit.Timer(stmt="pickle_wr.load_cpickle_gc()", setup="import pickle_wr")
        print t.timeit(1),'\n'
    

    확실히, 작업을 완료하는 데 더 적합한 방법이있을 수 있지만,이 해결 방법은 필요한 시간을 크게 줄입니다. (나를 위해, 843.04s에서 41.28s, 20x 주위로 감소했습니다)

  3. ==============================

    3.사전을 하나의 파일에 저장하려고하면 큰 파일이로드 속도가 느려집니다. 가장 쉬운 방법 중 하나는 디스크의 디렉토리에 사전을 작성하는 것입니다. 각 사전 항목은 개별 파일입니다. 그런 다음 여러 스레드에서 파일을 pickle 및 unpickle 처리 (또는 다중 처리 사용) 할 수 있습니다. 매우 큰 사전의 경우, 선택한 serializer와 상관없이 단일 파일에서 읽고 읽는 것보다 훨씬 빠릅니다. klepto와 joblib 같은 패키지가 이미 있습니다 (위의 모든 것이 아니라면). 나는 그 패키지를 체크 아웃했다. (참고 : 저는 klepto 저자입니다. https://github.com/uqfoundation/klepto를 참조하십시오.)

    사전을 하나의 파일에 저장하려고하면 큰 파일이로드 속도가 느려집니다. 가장 쉬운 방법 중 하나는 디스크의 디렉토리에 사전을 작성하는 것입니다. 각 사전 항목은 개별 파일입니다. 그런 다음 여러 스레드에서 파일을 pickle 및 unpickle 처리 (또는 다중 처리 사용) 할 수 있습니다. 매우 큰 사전의 경우, 선택한 serializer와 상관없이 단일 파일에서 읽고 읽는 것보다 훨씬 빠릅니다. klepto와 joblib 같은 패키지가 이미 있습니다 (위의 모든 것이 아니라면). 나는 그 패키지를 체크 아웃했다. (참고 : 저는 klepto 저자입니다. https://github.com/uqfoundation/klepto를 참조하십시오.)

  4. from https://stackoverflow.com/questions/26860051/how-to-reduce-the-time-taken-to-load-a-pickle-file-in-python by cc-by-sa and MIT license