2019.10.19この記事は約9分で読めます。スクレイピングで大量のデータを取得するプログラムや機械学習のプログラムを作成すると、プログラムの内部では同じような処理を何度も繰り返しており、並列化させることで処理が高速化される可能性があります。以前の投稿で紹介しましたが、我が家には6コア12スレッドのサーバーがあるので、このスペックをフルに生かすためにも並列化処理を組み込まない手はありません。Linux(Ubuntu)自作PCのパーツ購入ということで、pythonの並列化処理を試しに使ってみたので、備忘録として書いておきたいと思います。スポンサーリンク目次concurrent.futuresモジュールPythonの並列処理で注意すべき点(グローバルインタープリタロック)並列化処理を実装してみる関数の準備シングルプロセスマルチスレッドマルチプロセス関数に複数の引数を渡したいときまとめconcurrent.futuresモジュールpythonで並列化処理を行うライブラリはいくつかあるようですが、python3.2で追加された標準モジュールであるconcurrent.futuresというモジュールを使うのが良さそうです。公式ドキュメントはこちらになります。ドキュメントdocs.python.orgPythonの並列処理で注意すべき点(グローバルインタープリタロック)Pythonの並列化処理の方法にはマルチスレッドとマルチプロセスの2種類があります。マルチスレッドはCPUのスレッドを使用し処理を行い、マルチプロセスは別のサブプロセスを起動して処理します。したがって、理論上はマルチスレッドはCPUのスレッド数、マルチプロセスはCPUのコア数が並列化の上限となります。私のサーバーは6コア、12スレッドなので、マルチプロセスを行う場合は6並列、マルチスレッドの場合は12並列まで可能という感じでしょう。Pythonではマルチスレッドの際に、スレッドセーフ(グローバル変数の意図しない書き込みやDBのデッドロックを防ぐ)のためにグローバルインタープリタロック(GIL)が採用されているそうです。スレッドセーフにしてくれているのはありがたいですが、その反面マルチスレッドの恩恵をあまり受けられないというデメリットがあるのは致し方有りません。詳細はこちらのサイトを御覧ください。Pythonで並列処理を学習し始めたものの、「プロセス」「スレッド」「GIL」の話が出てきて白目になったのでまとめました。|...qiita.com並列化処理を実装してみる詳細な説明は上記のサイトに委ねるとして、実際の実装例を示したいと思います。並列処理を行うサンプルの関数を定義します。ここでは1〜Nまでの数字を足し合わせる関数です。途中にtime.sleepを入れて0.1秒ストップする処理をしています。実はこの程度の計算であれば、time.sleepを入れなければ、並列化処理しない(シングルプロセス)の方が早いです。(理由はサブプロセスなどを立ち上げるオーバーヘッドに時間を要するからだと思います。)ただ、マルチスレッドとマルチプロセスの違いをわかりやすくするために入れていますので、その点ご留意ください。sシングルプロセスまずは、通常のシングルプロセスで実行してみたいと思います。時間を計測するために、time.time()を入れていますが計算をしている(後ほど並列化したい)箇所は8〜12行目の計算処理という部分になります。処理時間:5.534s処理時間は約5.5秒でした。マルチスレッド次は、Pythonのマルチスレッディングを使用します。上記の8〜12行目の箇所を下記のように変更します。並列処理結果はretという変数に格納されます。ret]とすることでlist形式にすることができます。処理時間:1.405s処理時間は約1.4秒となり早くなっております。これをスレッド数を12まで増やしたいと思います。上記コードの9行目の(6)の部分を(12)に変更します。処理時間:1.005s1/2とはまではいきませんでしたが、処理時間はさらに早くなりました。マルチプロセス次に、Pythonのマルチプロセスを使用します。マルチスレッドのThreadPoolExecutorをProcessPoolExecutorに書き換えるだけでOKです。処理時間:1.422s処理時間は約1.4秒となりマルチスレッド(スレッド数6)の場合とほぼ同じでした。関数に複数の引数を渡したいとき上記のコードでは、引数が足し算したい数:Nのみでしたが、複数の引数を渡したい場合もあると思います。その場合は、一旦リストに引数を入れて渡すことになると思います。例として、先程1〜Nまでの足し算だったのを、足し算の最初の値(from_)と最後の値(to_)を変えて見たいと思います。関数を次のように定義します。s引数は次のように与えます。from_は3〜12まで、to_は3の倍数です。30]]このリスト形式のargsを引数として、下記のように記述すれば複数の引数を渡すことができます。>>処理時間:1.833sまとめ今回は、pythonの標準モジュールであるconcurren.futuresのThreadPoolExecutorとProcessPoolExecutorを使ってみました。同じような計算を大量に回る際にはプログラムの高速化につながると思います。詳しく知りたい方は以下の書籍が良いかと思います。コメントをキャンセルメールアドレスが公開されることはありません。*サイト次回のコメントで使用するためブラウザーに自分の名前、メールアドレス、サイトを保存する。29アーカイブ2020年1月2019年12月2019年11月2019年10月2019年9月2019年8月2019年7月2019年6月2019年5月topix脱サラ、転職、副収入に役立つかもしれないことをブログに書き綴っています。29アーカイブ2020年1月2019年12月2019年11月2019年10月2019年9月2019年8月2019年7月2019年6月2019年5月topix脱サラ、転職、副収入に役立つかもしれないことをブログに書き綴っています。topixをフォローするスポンサーリンクタイトルとURLをコピーしました。