Pythonのpickle.dumpに3番目の引数がある話
cPickle.dump(obj, f, -1)みたいな使い方を見て、なんだこの-1?と思ったので調べてみた。簡潔に言えば、これはフォーマットの指定で、指定しなかったときは後方互換性のために初期のASCII形式での保存がおこなわれる。-1ってのは最新のを使えという意味で、今ならバージョン2ということになる。
There are currently 3 different protocols which can be used for pickling.
- Protocol version 0 is the original ASCII protocol and is backwards compatible with earlier versions of Python.
- Protocol version 1 is the old binary format which is also compatible with earlier versions of Python.
- Protocol version 2 was introduced in Python 2.3. It provides much more efficient pickling of new-style classes.
http://docs.python.org/library/pickle.html
で、気になるのはファイルサイズとか速度とかだよね。
計測方法
Numpyのndarrayで1000x1000のサイズの0〜1の乱数が入った行列を作り、それを文字列にシリアライズしてサイズと時間を計測した。サイズは文字列の長さ、時間はipythonの%timeitで適当な回数繰り返して計測した。
時間
まあざっくり100倍違いますね。
%timeit s = cPickle.dumps(m) 1 loops, best of 3: 1.14 s per loop %timeit s = cPickle.dumps(m, 1) 100 loops, best of 3: 18.4 ms per loop %timeit s = cPickle.dumps(m, 2) 100 loops, best of 3: 18.4 ms per loop
サイズ
こちらの差は3倍弱。
len(cPickle.dumps(m)) 22217167 len(cPickle.dumps(m, 1)) 8000141 len(cPickle.dumps(m, 2)) 8000136
まとめ
version 1と2の違いは対象がndarrayだとよくわからないけど、少なくともversion 0を使い続ける明確な理由がないなら新しいバージョンを使った方がよさそう。
おまけ
Cで書かれていないpickleの方を使った場合、version 0では速度に大した差が出ないが、1以降なら2〜3倍遅い。
%timeit s = pickle.dumps(m) 1 loops, best of 3: 1.16 s per loop %timeit s = pickle.dumps(m, 1) 10 loops, best of 3: 42.3 ms per loop %timeit s = pickle.dumps(m, 2) 10 loops, best of 3: 42.1 ms per loop