- 作者: Micha Gorelick,Ian Ozsvald,相川愛三
- 出版社/メーカー: オライリージャパン
- 発売日: 2015/11/20
- メディア: 大型本
- この商品を含むブログ (3件) を見る
Pythonの高速化技法について一歩踏み込んだプロユースの解説書。ボトルネックの測定方法から、最適なデータ構造の使い分け、CythonやPyPyなどのコンパイラの比較、numpyなどのパッケージの使い方、マルチコアCPUの活用法、メモリ効率を劇的に改善するトライ構造や近似計算まで、シンプルな実例プログラムを用いながらわかりやすく説明します。高性能なプログラムの書き方だけでなく、高性能なシステムの作り方を総合的に学ぶことができるPythonエキスパート必携の一冊です。
https://www.oreilly.co.jp/books/9784873117409/
ここにも書いてあるように、プロファイリングのやり方からデータ構造、Cコンパイル・並列並行処理など幅広い内容が扱われていた。CPython以外の実装について勉強しようと思ってこの本を読み始めたので、個人的には「7章 Cにコンパイルする」が特に面白かった。
また普段はI/Oバウンドなプログラムを書くことが多いので、RAM使用量の削減とかそのためのプロファイリングなどCPUバウンドなプログラムについての知見が得られてよい。
時間ができたら次は積ん読になってるCythonのやつを読もう。
- 作者: Kurt W. Smith,中田秀基,長尾高弘
- 出版社/メーカー: オライリージャパン
- 発売日: 2015/06/19
- メディア: 大型本
- この商品を含むブログ (3件) を見る
読書メモ
3章 リストとタプル
- リストは動的な配列
- タプルは静的な配列
- サイズが1~20の小さなタプルについては、使われなくなってもメモリがOSに返却されず、将来の再利用のために保持される
>>> %timeit l = [0, 1, 2, 3, 4, 5 ,6, 7, 8 ,9] 96.8 ns ± 1.22 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each) >>> %timeit t = (0, 1, 2, 3, 4, 5 ,6, 7, 8 ,9) 16.4 ns ± 0.205 ns per loop (mean ± std. dev. of 7 runs, 100000000 loops each)
4章 辞書と集合
- 辞書と集合は、ハッシュ表を使ってO(1)の検索と挿入を実現
- ハッシュ可能なデータ型であればキーに使える
- 異なるキーが同じハッシュ値になることが(ハッシュ値の衝突)起こる
- 衝突数を適度に抑えるには、要素数がハッシュ表のサイズの2/3を超えないようにする
- ハッシュ表は2/3を超えるとサイズを拡張する
- 「ハッシュ関数がどれほどよく分散するか」という概念をハッシュ関数のエントロピーと呼ぶ
5章 イテレータとジェネレータ
- ジェネレータと無限数列
def fibonacci(): i, j = 0, 1 while True: yield j i, j = j, i +j
def fibonacci_succinct(): is_odd = lambda x: x % 2 first_5000 = islice(fibonacci(), 0, 5000) return sum(1 for x in first_5000 if is_odd(x))
- ジェネレータで省メモリで高速な処理が可能
- 遅延評価
6章 行列とベクトルの計算
メモリ断片化
- リストはデータそのものではなくポインタを保持している
- どんな型でも格納できるのでたいていの場合では便利
- ベクトルや行列の演算においては、著しい性能劣化の原因に
- データをメモリ上の連続した1つのブロックとして扱うことができれば、データ全体を一回の操作で移動できる
- データが断片化されていると、ブロック全体を移動できず、各位要素をばらばらに移動する必要がある
- ループがベクトル化に対応していない
- 一度に1つの要素を演算するループを、ひとまとまりのデータに対して同時に処理したい
- リストはデータそのものではなくポインタを保持している
numpy導入
7章 Cにコンパイルする
AOTコンパイラ
- Cython
- Shed Skin
- Pythran
- CPython Compiler Tools
- ここに色々まとまってる
- PyPyはPython3・Numpy対応できるように進化しててすごい
- ctypes
- 外部関数インターフェース
- 引数をCの型へキャストする必要あり
- 複雑でメンテナンスが大変になりやすい
- cffi
- http://cffi.readthedocs.io/en/latest/
- 関数や構造体の定義を理解できるCのパーサーが内蔵されている
- なのでCのコードを書くだけでOK
- f2py
8章 並行処理
- イベントループで並行処理を実現
- 2つの考え方
- コールバック
- Future
- 2つの考え方
- gevent
- http://www.gevent.org/
- 標準 I/O 関数を非同期に変えるモンキーパッチ
- 軽量スレッドで並行処理ができるGreenlet
- 複数のCPUを使わずに、イベントループを使うことによって I/O 待ちの間にgeventのスケジューラがGreenletを切り替える
- grequests知らなかった
- https://github.com/kennethreitz/grequests
- requests x gevent
- tornado
- http://www.tornadoweb.org/en/stable/
- コールバックの方法を採用していたけど、バージョン3.xからは、互換性を保ったまま、コルーチ 風の処理が追加された
- イベントループは全体で動作していて、非同期I/Oにかぎらず プログラムの実行の流れを制御している
- geventはiwait関数が実行している間だけイベントループが動作
- asyncio
- asyncioライブラリは、tornadoやgeventのようなモジュールと組み合わせて、同じイベントループで動作させることも可能
- やっぱり標準ライブラリがいいよね
9章 multiprocessingモジュール
- embarrassingly parallel問題(あきれるほど 簡単に並列化可能な問題)
- ジョブを互いに独立な単位に分割する
- ワーカーによって計算時間にばらつきがあるのなら、処理の順序をランダム化することを検討する
- 処理の遅い順に並べて、もっとも遅い処理から先に片づける
- 検証された理由がないかぎり、デフォルトのchunksizeを用いる
- チャンク数を物理コア数の倍数にすること
- 可能なら自前で非同期システムを作るのは避ける
- geventのような成熟したライブラリがbetter
- 外部のキュー管理システムについてもCeleryとかを使おう
10章 クラスタとジョブキュー
- Parallel Python
- https://pypi.python.org/pypi/pp
- multiprocessingを用いたコードを、1台のマルチコアのマシンから複数台のマシンを使うように簡単に変更できる
- リモートマシンにコードや静的なデータを分配する機能はない
- embarrassingly parallelな処理を小さなローカルクラスタで実行するのに適している
- IPython Parallel
- https://github.com/ipython/ipyparallel
- ZeroMQをメッセージング用ミドルウェアとして利用
- NSQ
- https://github.com/nsqio/nsq
- 分散型メッセージングミドルウェア
- Celery
- Gearman
- PyRes
- SQS