前置き
Pythonの並列処理といえば、threading
やmultiprocessing
、concurrent
が代表的だが、常々前置きが多いのがネックであった。
慣れてしまえば気にならないのだろうが、そう頻繁に使うものでもないので、慣れるまで使うことは少ない。
使うことが少ないので、必要になれば毎回使い方を検索するハメになる。
面倒で仕方がない。
そんな中出会ったのが「Ray」というライブラリ。
並列処理をサポートするライブラリだが、これがまぁ使いやすい。
- 使うcpuのコア数を決めて
- 並列化したい関数を
@ray.remote
でデコレートして -
ray.get(func.remote(params))
するだけ
たったこれだけで記述できるのが素晴らしい。
皆も使って素晴らしさを体感しよう。
Rayの使い方
前述の通り、これだけ
1. 使うcpuの数を決めて
2. 並列化したい関数を @ray.remote でデコレートして
3. ray.get(func.remote(params)) するだけ
インストール
pip install ray
でインストールできる。
importも以下のように書くだけ。
import ray
1. 使うcpuの数を決めて
ここでのcpuの数は、論理コア数のこと。
デフォルト値の場合、(恐らく)全ての論理コアが食われるので注意。
以下の処理を最初に書くだけ。
ray.init(num_cpus=4)
この処理には少し時間が必要なので、上手く動かない場合は
ray.init(num_cpus=4)
time.sleep(1)
などとして少し待ってあげよう。
2. 並列化したい関数を @ray.remote でデコレートして
並列化といえばスクレイピング(偏見)なので、seleniumやbs4を用いた以下のような関数を想定する。
def get_page(url):
html = chrome_driver.get(url).page_source
bs = BeautifulSoup(html, features="lxml")
title = bs.get("title").title
with open(f"{title}.html", "w") as f:
f.write(html)
この関数はchrome_driver.get(url)
の処理で待ちが発生するため、記事が多いほど時間がかかってしまうのは当然である。
そこで、@ray.remote
を使って並列処理に対応させる。
@ray.remote
def get_page(url):
# 変更不要なので省略
なんと、たった1行書くだけで準備完了。
お手軽すぎる。
3. ray.get(func.remote(params)) するだけ
最後に、以下のように書くことで並列化させて実行する。
今回は設定したcpuの個数分だけ並列させる。
urls = [...]
rays = []
for url in urls:
r = get_page.remote(url)
rays.append(r)
if len(rays) == 4:
ray.get(rays)
rays = []
if len(ray) != 0:
ray.get(rays)
たったこれだけで並列化が実現できる。
あとがき
皆もこの神ライブラリ「Ray」を使って、煩雑な並列処理コードとサヨナラしよう!
参考記事