SlideShare a Scribd company logo
はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お
async/await の向こう側
PyCon Kyushu 2022 Kumamoto
Atsushi Odagiri
2022-01-22
Atsushi Odagiri
async/await の向こう側
はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お
はじめに
Atsushi Odagiri
async/await の向こう側
はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お
お前誰よ
aodag
Atsushi Odagiri
株式会社オープンコレクター
python1.5 とかから
Atsushi Odagiri
async/await の向こう側
はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お
アジェンダ
asyncio とコルーチン
コルーチン
非同期 IO
Atsushi Odagiri
async/await の向こう側
はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お
async/await と asyncio
Atsushi Odagiri
async/await の向こう側
はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お
async/await と asyncio
Python 3.4 asyncio 導入
Python 3.5 async/await 構文導入
Atsushi Odagiri
async/await の向こう側
はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お
asyncio
非同期 IO をコルーチンで扱えるライブラリ
コルーチンを扱うための関数も用意されている
Atsushi Odagiri
async/await の向こう側
はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お
async/await
コルーチンを扱うための構文
await でサブコルーチンを呼び出して大きなコルーチンを作る
await にはサブコルーチンが必要
await だけでコルーチンを作ることができない
__await__ スペシャルメソッドで awaitable な型を定義
Atsushi Odagiri
async/await の向こう側
はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お
コルーチンとは?
Atsushi Odagiri
async/await の向こう側
はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お
並列処理
並列処理 (concurrent)
プリエンプティブなスレッド
コルーチン (協調スレッド)
Atsushi Odagiri
async/await の向こう側
はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お
プリエンプティブな並列処理
主に OS の機能を使う
gevent のようにユーザーランドのみで行う実装もある
コンテキストの切り替えは実行中のプログラムが意識するこ
となく行われる
いつ切り替わるかわからないので共有リソースの扱いに注意
IO 待ちにる場合なども自動で行われるように作られている
Atsushi Odagiri
async/await の向こう側
はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お
協調スレッドによる並列処理
協調スレッド
自分で処理を明け渡す
yield を使う
Atsushi Odagiri
async/await の向こう側
はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お
どうしてジェネレーターでコルーチンが作れるのか?
yield で処理を明け渡す
send されると値を受け取って処理を再開する
yield from でコルーチンの結果を取得
Atsushi Odagiri
async/await の向こう側
はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お
ジェネレーターでコルーチンを書く
def counter(n: int, name: str) -> typing.Generator[None, No
count = 0
while count < n:
yield
print(f"{name}: {count}")
count += 1
Atsushi Odagiri
async/await の向こう側
はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お
ジェネレーターで書いたコルーチンを動かす
coroutines = [counter(10, "counter1"), counter(5, "counter2
while coroutines:
for c in coroutines:
try:
c.send(None)
except StopIteration:
coroutines.remove(c)
Atsushi Odagiri
async/await の向こう側
はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お
コルーチンを動かしてみた結果
counter1: 0
counter2: 0
counter1: 1
counter2: 1
counter1: 2
counter2: 2
counter1: 3
counter2: 3
counter1: 4
counter2: 4
counter1: 5
counter1: 6
counter1: 7
counter1: 8
counter1: 9
Atsushi Odagiri
async/await の向こう側
はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お
yield from で結果を取得
yield from でサブコルーチンを呼ぶ
サブコルーチンまで含めて大きなコルーチンになる
サブコルーチンが return した値が yield from で返って
くる
Atsushi Odagiri
async/await の向こう側
はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お
サブコルーチンを yield from で呼ぶ
def twice_counter() -> typing.Generator[None, None, None]:
yield from counter(10, "counter1")
yield from counter(5, "counter2")
Atsushi Odagiri
async/await の向こう側
はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お
yield 式って結局なに?
next したときにジェネレーターとしての要素を返す
次に next されるまで処理が止まる
値を渡すときは send を使う
Atsushi Odagiri
async/await の向こう側
はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お
await vs yield from
await サブコルーチンを起動して、結果を受け取る
yield from サブジェネレータを起動して、ジェネレータの
要素とする + 結果を受け取る
await は途中経過を気にしないようになって、よりコルーチ
ンとしての機能に特化している
Atsushi Odagiri
async/await の向こう側
はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お
タスク!future!コルーチンを利用するための
ツール
Atsushi Odagiri
async/await の向こう側
はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お
イベントループ
イベントについては後述
コルーチンはジェネレーターなので send してくれるループ
が必要
複数のコルーチンを順番に少しずつ send することでそれぞ
れのコルーチンが実行される
Atsushi Odagiri
async/await の向こう側
はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お
イベントループの素朴な実装
非同期 IO に関する処理
tasks: typing.List[typing.Generator[None, None, None]] = []
removing: typing.Set[typing.Generator[None, None, None]] =
while True:
for t in tasks:
try:
t.send(None)
except StopIteration:
removing.add(t)
except Exception as e:
print(e)
removing.add(t)
for t in removing:
tasks.remove(t)
removing = set()
Atsushi Odagiri
async/await の向こう側
はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お
future で非同期に結果を得る
結果が入る場所を用意してコルーチンに渡す
他のコルーチンで後から結果を確認
Atsushi Odagiri
async/await の向こう側
はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お
Future の素朴な実装
class Future(typing.Generic[T]):
_result: typing.Union[T, None]
def __init__(self):
self._result = None
self._done = False
def done(self, value: T):
self._result = value
self._done = True
def get_result(self) -> typing.Generator[None, None, T]
while self._result is None:
yield
return self._result
Atsushi Odagiri
async/await の向こう側
はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お
コルーチンと future をまとめてタスクにする
タスクは受け取ったコルーチンをサブコルーチン呼び出して
結果を future に入れるコルーチン
並列で実行するようにタスクをイベントループに追加
Atsushi Odagiri
async/await の向こう側
はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お
タスクの素朴な実装
def task(coro: typing.Generator[None, None, T], f: Future[T
result: T = yield from coro
f.done(result)
def create_task(coro: typing.Generator[None, None, T]) -> t
f: Future[T] = Future()
tasks.append(task(coro, f))
return f.get_result()
Atsushi Odagiri
async/await の向こう側
はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お
タスクを使った非同期処理
def twice_counter() -> typing.Generator[None, None, None]:
t1 = create_task(counter(10, "counter1"))
t2 = create_task(counter(5, "counter2"))
yield from t1
yield from t2
Atsushi Odagiri
async/await の向こう側
はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お
非同期 IO
Atsushi Odagiri
async/await の向こう側
はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お
非同期 IO
非同期 IO とはなにか
IO 待ちしている間は CPU は暇
IO 待ちしている間に別のタスクを実行したい
IO の状況が変わるまで放置
Atsushi Odagiri
async/await の向こう側
はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お
イベントループのイベントとは?
IO が読み取り可能になった
IO が書き込み可能になった
Atsushi Odagiri
async/await の向こう側
はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お
非同期 IO(コールバック)
コールバックで IO を待つ
イベント発生時にコールバックを呼ぶ
コールバックが呼ばれるまで他の処理ができる
Atsushi Odagiri
async/await の向こう側
はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お
selectors モジュール
非同期 IO
select/poll などの標準的な仕組み
kequeue, epoll, IOCP のような OS ごとの仕組み
selectors モジュールは様々な OS 向けの非同期 IO の仕組みを
共通のインターフェイスで使えるようにしたラッパー
Atsushi Odagiri
async/await の向こう側
はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お
selectors モジュールを使う処理
監視対象を登録する register
ポーリングしてイベントを取得 select
監視を解除 unregister
Atsushi Odagiri
async/await の向こう側
はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お
非同期 IO をコルーチンで処理する
イベントループ内でポーリングする
Atsushi Odagiri
async/await の向こう側
はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お
素朴な echo サーバー
accept したらそのまま echo 処理を行う
1 つのクライアントの処理が終わらないと他のクライアント
の接続を処理できない
sock = socket.socket()
sock.bind(('localhost', 1234))
sock.listen(100)
while True:
conn, addr = sock.accept()
while True:
data = conn.recv(1000)
if data:
conn.send(data)
else:
conn.close()
break
Atsushi Odagiri
async/await の向こう側
はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お
マルチスレッドな echo サーバー
accept したら子スレッドを作成してクライアントソケットを
渡す
def accept(conn: socket.socket):
try:
data = conn.recv(1000)
while data:
conn.send(data)
data = conn.recv(1000)
finally:
conn.close()
while True:
conn, _ = sock.accept()
threading.Thread(target=accept, args=(conn,)).start()
Atsushi Odagiri
async/await の向こう側
はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お
スレッドプールを使う echo サーバー
accept したらクライアントソケットをスレッドプールに渡す
executor = ThreadPoolExecutor()
while True:
conn, _ = sock.accept()
executor.submit(accept, conn)
Atsushi Odagiri
async/await の向こう側
はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お
selector にコールバックを使って echo サーバー
コールバック処理
def accept(sock, _):
conn, addr = sock.accept() # Should be ready
print('accepted', conn, 'from', addr)
conn.setblocking(False)
sel.register(conn, selectors.EVENT_READ, read)
def read(conn, _):
data = conn.recv(1000) # Should be ready
if data:
print('echoing', repr(data), 'to', conn)
conn.send(data) # Hope it won't block
else:
print('closing', conn)
sel.unregister(conn)
Atsushi Odagiri
async/await の向こう側
はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お
selector にコールバックを使って echo サーバー
selector や socket の準備
sel = selectors.DefaultSelector()
sock = socket.socket()
sock.bind(('localhost', 1234))
sock.listen(100)
sock.setblocking(False)
sel.register(sock, selectors.EVENT_READ, accept)
while True:
events = sel.select()
for key, mask in events:
callback = key.data
callback(key.fileobj, mask)
Atsushi Odagiri
async/await の向こう側
はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お
selector をコルーチンで呼び出せるようにして echo サー
バー (1)
recv をコルーチンで扱えるようにする
def read_async(conn:socket.socket):
f: Future[bytes] = Future()
def callback(conn: socket.socket, _):
sel.unregister(conn)
f.done(conn.recv(1000))
sel.register(conn, selectors.EVENT_READ, callback)
return f.get_result()
Atsushi Odagiri
async/await の向こう側
はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お
selector をコルーチンで呼び出せるようにして echo サー
バー (2)
send をコルーチンで扱えるようにする
def send_async(conn:socket.socket, data: bytes):
f: Future[int] = Future()
def callback(conn: socket.socket, _):
sel.unregister(conn)
f.done(conn.send(data))
sel.register(conn, selectors.EVENT_WRITE, callback)
return f.get_result()
Atsushi Odagiri
async/await の向こう側
はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お
selector をコルーチンで呼び出せるようにして echo サー
バー (3)
echo タスク
def accept(sock, _):
conn, _ = sock.accept()
conn.setblocking(False)
create_task(read(conn))
def read(conn: socket.socket):
while True:
data = yield from read_async(conn)
if data:
yield from send_async(conn, data)
else:
break
conn.close()
Atsushi Odagiri
async/await の向こう側
はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お
selector をコルーチンで呼び出せるようにして echo サー
バー (4)
selector やソケットの準備
sel = selectors.DefaultSelector()
tasks: typing.List[typing.Generator[None, None, None]] = []
sock = socket.socket()
sock.bind(('localhost', 1234))
sock.listen(100)
sock.setblocking(False)
sel.register(sock, selectors.EVENT_READ, accept)
Atsushi Odagiri
async/await の向こう側
はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お
selector をコルーチンで呼び出せるようにして echo サー
バー (5)
イベントループ
while True:
events = sel.select()
for key, mask in events:
callback = key.data
callback(key.fileobj, mask)
removing: typing.Set[typing.Generator[None, None, None]
for t in tasks:
try:
t.send(None)
except StopIteration:
removing.add(t)
except Exception as e:
print(e)
Atsushi Odagiri
async/await の向こう側
はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お
おまけ
Atsushi Odagiri
async/await の向こう側
はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お
コルーチンでない awaitable
class AwaitableSample:
def __await__(self):
yield
return "hello"
Atsushi Odagiri
async/await の向こう側
はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お
コルーチンでない!
タスクが受け取るのはコルーチンであって awaitable 全般
ではないらしい
asyncio.create_task(AwaitableSample())
TypeError: a coroutine was expected,
got <__main__.AwaitableSample object at 0x7f4429c36100>
Atsushi Odagiri
async/await の向こう側
はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お
まとめ
Atsushi Odagiri
async/await の向こう側
はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お
まとめ
コルーチン
yield で処理を明け渡す協調スレッド (コルーチン)
yield from はコルーチンを起動して終了を待機する
タスクは起動したコルーチンと結果を受け取る Future の組
非同期 IO
OS ごとに異なる方法で IO の状態を監視
ポーリングして状態チェック
クライアント接続ごとにスレッドを消費しない
状態が変化するまでコルーチンで待つ
Atsushi Odagiri
async/await の向こう側
はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お
参考文献
PEP 255 – Simple Generators
PEP 380 – Syntax for Delegating to a Subgenerator -PEP 492
– Coroutines with async and await syntax
PEP 3156 – Asynchronous IO Support Rebooted: the “asyncio”
Module
Python3.4 当時の asyncio リファレンス
Atsushi Odagiri
async/await の向こう側

More Related Content

More from Atsushi Odagiri

Pythonでの開発を効率的に進めるためのツール設定
Pythonでの開発を効率的に進めるためのツール設定Pythonでの開発を効率的に進めるためのツール設定
Pythonでの開発を効率的に進めるためのツール設定
Atsushi Odagiri
 
Pythonとパッケージングと私
Pythonとパッケージングと私Pythonとパッケージングと私
Pythonとパッケージングと私
Atsushi Odagiri
 
Python3 移行への軌跡
Python3 移行への軌跡Python3 移行への軌跡
Python3 移行への軌跡
Atsushi Odagiri
 
パッケージングを支える技術 pyconjp2016
パッケージングを支える技術 pyconjp2016パッケージングを支える技術 pyconjp2016
パッケージングを支える技術 pyconjp2016
Atsushi Odagiri
 
Sqlalchemy sqlの錬金術
Sqlalchemy  sqlの錬金術Sqlalchemy  sqlの錬金術
Sqlalchemy sqlの錬金術
Atsushi Odagiri
 
Clack meetup #1 lt
Clack meetup #1 ltClack meetup #1 lt
Clack meetup #1 lt
Atsushi Odagiri
 
パッケージングの今
パッケージングの今パッケージングの今
パッケージングの今Atsushi Odagiri
 
パッケージングの今と未来
パッケージングの今と未来パッケージングの今と未来
パッケージングの今と未来Atsushi Odagiri
 
パッケージングの今と未来
パッケージングの今と未来パッケージングの今と未来
パッケージングの今と未来Atsushi Odagiri
 
Pyconjp2012 memory-of-europython
Pyconjp2012 memory-of-europythonPyconjp2012 memory-of-europython
Pyconjp2012 memory-of-europythonAtsushi Odagiri
 
What makes pyramid unique
What makes pyramid uniqueWhat makes pyramid unique
What makes pyramid uniqueAtsushi Odagiri
 
エキPy lt repoze.whoの紹介
エキPy lt repoze.whoの紹介エキPy lt repoze.whoの紹介
エキPy lt repoze.whoの紹介Atsushi Odagiri
 
Setup.pysetup.cfg
Setup.pysetup.cfgSetup.pysetup.cfg
Setup.pysetup.cfg
Atsushi Odagiri
 
BPStudy#54 そろそろPython3
BPStudy#54 そろそろPython3BPStudy#54 そろそろPython3
BPStudy#54 そろそろPython3Atsushi Odagiri
 
フレームワークなしでWSGIプログラミング
フレームワークなしでWSGIプログラミングフレームワークなしでWSGIプログラミング
フレームワークなしでWSGIプログラミング
Atsushi Odagiri
 

More from Atsushi Odagiri (20)

Pythonでの開発を効率的に進めるためのツール設定
Pythonでの開発を効率的に進めるためのツール設定Pythonでの開発を効率的に進めるためのツール設定
Pythonでの開発を効率的に進めるためのツール設定
 
Pythonとパッケージングと私
Pythonとパッケージングと私Pythonとパッケージングと私
Pythonとパッケージングと私
 
Python3 移行への軌跡
Python3 移行への軌跡Python3 移行への軌跡
Python3 移行への軌跡
 
パッケージングを支える技術 pyconjp2016
パッケージングを支える技術 pyconjp2016パッケージングを支える技術 pyconjp2016
パッケージングを支える技術 pyconjp2016
 
Sqlalchemy sqlの錬金術
Sqlalchemy  sqlの錬金術Sqlalchemy  sqlの錬金術
Sqlalchemy sqlの錬金術
 
Clack meetup #1 lt
Clack meetup #1 ltClack meetup #1 lt
Clack meetup #1 lt
 
Pyramid入門
Pyramid入門Pyramid入門
Pyramid入門
 
パッケージングの今
パッケージングの今パッケージングの今
パッケージングの今
 
パッケージングの今と未来
パッケージングの今と未来パッケージングの今と未来
パッケージングの今と未来
 
パッケージングの今と未来
パッケージングの今と未来パッケージングの今と未来
パッケージングの今と未来
 
Bplt11 form alchemy
Bplt11 form alchemyBplt11 form alchemy
Bplt11 form alchemy
 
Python3でwebアプリ
Python3でwebアプリPython3でwebアプリ
Python3でwebアプリ
 
Pyconjp2012 memory-of-europython
Pyconjp2012 memory-of-europythonPyconjp2012 memory-of-europython
Pyconjp2012 memory-of-europython
 
What makes pyramid unique
What makes pyramid uniqueWhat makes pyramid unique
What makes pyramid unique
 
エキPy lt repoze.whoの紹介
エキPy lt repoze.whoの紹介エキPy lt repoze.whoの紹介
エキPy lt repoze.whoの紹介
 
World plonedaylt
World plonedayltWorld plonedaylt
World plonedaylt
 
Setup.pysetup.cfg
Setup.pysetup.cfgSetup.pysetup.cfg
Setup.pysetup.cfg
 
BPStudy#54 そろそろPython3
BPStudy#54 そろそろPython3BPStudy#54 そろそろPython3
BPStudy#54 そろそろPython3
 
Form libraries
Form librariesForm libraries
Form libraries
 
フレームワークなしでWSGIプログラミング
フレームワークなしでWSGIプログラミングフレームワークなしでWSGIプログラミング
フレームワークなしでWSGIプログラミング
 

Recently uploaded

This is the company presentation material of RIZAP Technologies, Inc.
This is the company presentation material of RIZAP Technologies, Inc.This is the company presentation material of RIZAP Technologies, Inc.
This is the company presentation material of RIZAP Technologies, Inc.
chiefujita1
 
JSAI_類似画像マッチングによる器への印象付与手法の妥当性検証_ver.3_高橋りさ
JSAI_類似画像マッチングによる器への印象付与手法の妥当性検証_ver.3_高橋りさJSAI_類似画像マッチングによる器への印象付与手法の妥当性検証_ver.3_高橋りさ
JSAI_類似画像マッチングによる器への印象付与手法の妥当性検証_ver.3_高橋りさ
0207sukipio
 
遺伝的アルゴリズムと知識蒸留による大規模言語モデル(LLM)の学習とハイパーパラメータ最適化
遺伝的アルゴリズムと知識蒸留による大規模言語モデル(LLM)の学習とハイパーパラメータ最適化遺伝的アルゴリズムと知識蒸留による大規模言語モデル(LLM)の学習とハイパーパラメータ最適化
遺伝的アルゴリズムと知識蒸留による大規模言語モデル(LLM)の学習とハイパーパラメータ最適化
t m
 
LoRaWAN 4チャンネル電流センサー・コンバーター CS01-LB 日本語マニュアル
LoRaWAN 4チャンネル電流センサー・コンバーター CS01-LB 日本語マニュアルLoRaWAN 4チャンネル電流センサー・コンバーター CS01-LB 日本語マニュアル
LoRaWAN 4チャンネル電流センサー・コンバーター CS01-LB 日本語マニュアル
CRI Japan, Inc.
 
ReonHata_便利の副作用に気づかせるための発想支援手法の評価---行為の増減の提示による気づきへの影響---
ReonHata_便利の副作用に気づかせるための発想支援手法の評価---行為の増減の提示による気づきへの影響---ReonHata_便利の副作用に気づかせるための発想支援手法の評価---行為の増減の提示による気づきへの影響---
ReonHata_便利の副作用に気づかせるための発想支援手法の評価---行為の増減の提示による気づきへの影響---
Matsushita Laboratory
 
Generating Automatic Feedback on UI Mockups with Large Language Models
Generating Automatic Feedback on UI Mockups with Large Language ModelsGenerating Automatic Feedback on UI Mockups with Large Language Models
Generating Automatic Feedback on UI Mockups with Large Language Models
harmonylab
 
キンドリル ネットワークアセスメントサービスご紹介 今のネットワーク環境は大丈夫? 調査〜対策までご支援します
キンドリル ネットワークアセスメントサービスご紹介 今のネットワーク環境は大丈夫? 調査〜対策までご支援しますキンドリル ネットワークアセスメントサービスご紹介 今のネットワーク環境は大丈夫? 調査〜対策までご支援します
キンドリル ネットワークアセスメントサービスご紹介 今のネットワーク環境は大丈夫? 調査〜対策までご支援します
Takayuki Nakayama
 
論文紹介:Deep Learning-Based Human Pose Estimation: A Survey
論文紹介:Deep Learning-Based Human Pose Estimation: A Survey論文紹介:Deep Learning-Based Human Pose Estimation: A Survey
論文紹介:Deep Learning-Based Human Pose Estimation: A Survey
Toru Tamaki
 

Recently uploaded (8)

This is the company presentation material of RIZAP Technologies, Inc.
This is the company presentation material of RIZAP Technologies, Inc.This is the company presentation material of RIZAP Technologies, Inc.
This is the company presentation material of RIZAP Technologies, Inc.
 
JSAI_類似画像マッチングによる器への印象付与手法の妥当性検証_ver.3_高橋りさ
JSAI_類似画像マッチングによる器への印象付与手法の妥当性検証_ver.3_高橋りさJSAI_類似画像マッチングによる器への印象付与手法の妥当性検証_ver.3_高橋りさ
JSAI_類似画像マッチングによる器への印象付与手法の妥当性検証_ver.3_高橋りさ
 
遺伝的アルゴリズムと知識蒸留による大規模言語モデル(LLM)の学習とハイパーパラメータ最適化
遺伝的アルゴリズムと知識蒸留による大規模言語モデル(LLM)の学習とハイパーパラメータ最適化遺伝的アルゴリズムと知識蒸留による大規模言語モデル(LLM)の学習とハイパーパラメータ最適化
遺伝的アルゴリズムと知識蒸留による大規模言語モデル(LLM)の学習とハイパーパラメータ最適化
 
LoRaWAN 4チャンネル電流センサー・コンバーター CS01-LB 日本語マニュアル
LoRaWAN 4チャンネル電流センサー・コンバーター CS01-LB 日本語マニュアルLoRaWAN 4チャンネル電流センサー・コンバーター CS01-LB 日本語マニュアル
LoRaWAN 4チャンネル電流センサー・コンバーター CS01-LB 日本語マニュアル
 
ReonHata_便利の副作用に気づかせるための発想支援手法の評価---行為の増減の提示による気づきへの影響---
ReonHata_便利の副作用に気づかせるための発想支援手法の評価---行為の増減の提示による気づきへの影響---ReonHata_便利の副作用に気づかせるための発想支援手法の評価---行為の増減の提示による気づきへの影響---
ReonHata_便利の副作用に気づかせるための発想支援手法の評価---行為の増減の提示による気づきへの影響---
 
Generating Automatic Feedback on UI Mockups with Large Language Models
Generating Automatic Feedback on UI Mockups with Large Language ModelsGenerating Automatic Feedback on UI Mockups with Large Language Models
Generating Automatic Feedback on UI Mockups with Large Language Models
 
キンドリル ネットワークアセスメントサービスご紹介 今のネットワーク環境は大丈夫? 調査〜対策までご支援します
キンドリル ネットワークアセスメントサービスご紹介 今のネットワーク環境は大丈夫? 調査〜対策までご支援しますキンドリル ネットワークアセスメントサービスご紹介 今のネットワーク環境は大丈夫? 調査〜対策までご支援します
キンドリル ネットワークアセスメントサービスご紹介 今のネットワーク環境は大丈夫? 調査〜対策までご支援します
 
論文紹介:Deep Learning-Based Human Pose Estimation: A Survey
論文紹介:Deep Learning-Based Human Pose Estimation: A Survey論文紹介:Deep Learning-Based Human Pose Estimation: A Survey
論文紹介:Deep Learning-Based Human Pose Estimation: A Survey
 

async/await の向こう側 PyCon Kyushu 2022

  • 1. はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お async/await の向こう側 PyCon Kyushu 2022 Kumamoto Atsushi Odagiri 2022-01-22 Atsushi Odagiri async/await の向こう側
  • 2. はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お はじめに Atsushi Odagiri async/await の向こう側
  • 3. はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お お前誰よ aodag Atsushi Odagiri 株式会社オープンコレクター python1.5 とかから Atsushi Odagiri async/await の向こう側
  • 4. はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お アジェンダ asyncio とコルーチン コルーチン 非同期 IO Atsushi Odagiri async/await の向こう側
  • 5. はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お async/await と asyncio Atsushi Odagiri async/await の向こう側
  • 6. はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お async/await と asyncio Python 3.4 asyncio 導入 Python 3.5 async/await 構文導入 Atsushi Odagiri async/await の向こう側
  • 7. はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お asyncio 非同期 IO をコルーチンで扱えるライブラリ コルーチンを扱うための関数も用意されている Atsushi Odagiri async/await の向こう側
  • 8. はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お async/await コルーチンを扱うための構文 await でサブコルーチンを呼び出して大きなコルーチンを作る await にはサブコルーチンが必要 await だけでコルーチンを作ることができない __await__ スペシャルメソッドで awaitable な型を定義 Atsushi Odagiri async/await の向こう側
  • 9. はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お コルーチンとは? Atsushi Odagiri async/await の向こう側
  • 10. はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お 並列処理 並列処理 (concurrent) プリエンプティブなスレッド コルーチン (協調スレッド) Atsushi Odagiri async/await の向こう側
  • 11. はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お プリエンプティブな並列処理 主に OS の機能を使う gevent のようにユーザーランドのみで行う実装もある コンテキストの切り替えは実行中のプログラムが意識するこ となく行われる いつ切り替わるかわからないので共有リソースの扱いに注意 IO 待ちにる場合なども自動で行われるように作られている Atsushi Odagiri async/await の向こう側
  • 12. はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お 協調スレッドによる並列処理 協調スレッド 自分で処理を明け渡す yield を使う Atsushi Odagiri async/await の向こう側
  • 13. はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お どうしてジェネレーターでコルーチンが作れるのか? yield で処理を明け渡す send されると値を受け取って処理を再開する yield from でコルーチンの結果を取得 Atsushi Odagiri async/await の向こう側
  • 14. はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お ジェネレーターでコルーチンを書く def counter(n: int, name: str) -> typing.Generator[None, No count = 0 while count < n: yield print(f"{name}: {count}") count += 1 Atsushi Odagiri async/await の向こう側
  • 15. はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お ジェネレーターで書いたコルーチンを動かす coroutines = [counter(10, "counter1"), counter(5, "counter2 while coroutines: for c in coroutines: try: c.send(None) except StopIteration: coroutines.remove(c) Atsushi Odagiri async/await の向こう側
  • 16. はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お コルーチンを動かしてみた結果 counter1: 0 counter2: 0 counter1: 1 counter2: 1 counter1: 2 counter2: 2 counter1: 3 counter2: 3 counter1: 4 counter2: 4 counter1: 5 counter1: 6 counter1: 7 counter1: 8 counter1: 9 Atsushi Odagiri async/await の向こう側
  • 17. はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お yield from で結果を取得 yield from でサブコルーチンを呼ぶ サブコルーチンまで含めて大きなコルーチンになる サブコルーチンが return した値が yield from で返って くる Atsushi Odagiri async/await の向こう側
  • 18. はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お サブコルーチンを yield from で呼ぶ def twice_counter() -> typing.Generator[None, None, None]: yield from counter(10, "counter1") yield from counter(5, "counter2") Atsushi Odagiri async/await の向こう側
  • 19. はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お yield 式って結局なに? next したときにジェネレーターとしての要素を返す 次に next されるまで処理が止まる 値を渡すときは send を使う Atsushi Odagiri async/await の向こう側
  • 20. はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お await vs yield from await サブコルーチンを起動して、結果を受け取る yield from サブジェネレータを起動して、ジェネレータの 要素とする + 結果を受け取る await は途中経過を気にしないようになって、よりコルーチ ンとしての機能に特化している Atsushi Odagiri async/await の向こう側
  • 21. はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お タスク!future!コルーチンを利用するための ツール Atsushi Odagiri async/await の向こう側
  • 22. はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お イベントループ イベントについては後述 コルーチンはジェネレーターなので send してくれるループ が必要 複数のコルーチンを順番に少しずつ send することでそれぞ れのコルーチンが実行される Atsushi Odagiri async/await の向こう側
  • 23. はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お イベントループの素朴な実装 非同期 IO に関する処理 tasks: typing.List[typing.Generator[None, None, None]] = [] removing: typing.Set[typing.Generator[None, None, None]] = while True: for t in tasks: try: t.send(None) except StopIteration: removing.add(t) except Exception as e: print(e) removing.add(t) for t in removing: tasks.remove(t) removing = set() Atsushi Odagiri async/await の向こう側
  • 24. はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お future で非同期に結果を得る 結果が入る場所を用意してコルーチンに渡す 他のコルーチンで後から結果を確認 Atsushi Odagiri async/await の向こう側
  • 25. はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お Future の素朴な実装 class Future(typing.Generic[T]): _result: typing.Union[T, None] def __init__(self): self._result = None self._done = False def done(self, value: T): self._result = value self._done = True def get_result(self) -> typing.Generator[None, None, T] while self._result is None: yield return self._result Atsushi Odagiri async/await の向こう側
  • 26. はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お コルーチンと future をまとめてタスクにする タスクは受け取ったコルーチンをサブコルーチン呼び出して 結果を future に入れるコルーチン 並列で実行するようにタスクをイベントループに追加 Atsushi Odagiri async/await の向こう側
  • 27. はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お タスクの素朴な実装 def task(coro: typing.Generator[None, None, T], f: Future[T result: T = yield from coro f.done(result) def create_task(coro: typing.Generator[None, None, T]) -> t f: Future[T] = Future() tasks.append(task(coro, f)) return f.get_result() Atsushi Odagiri async/await の向こう側
  • 28. はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お タスクを使った非同期処理 def twice_counter() -> typing.Generator[None, None, None]: t1 = create_task(counter(10, "counter1")) t2 = create_task(counter(5, "counter2")) yield from t1 yield from t2 Atsushi Odagiri async/await の向こう側
  • 29. はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お 非同期 IO Atsushi Odagiri async/await の向こう側
  • 30. はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お 非同期 IO 非同期 IO とはなにか IO 待ちしている間は CPU は暇 IO 待ちしている間に別のタスクを実行したい IO の状況が変わるまで放置 Atsushi Odagiri async/await の向こう側
  • 31. はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お イベントループのイベントとは? IO が読み取り可能になった IO が書き込み可能になった Atsushi Odagiri async/await の向こう側
  • 32. はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お 非同期 IO(コールバック) コールバックで IO を待つ イベント発生時にコールバックを呼ぶ コールバックが呼ばれるまで他の処理ができる Atsushi Odagiri async/await の向こう側
  • 33. はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お selectors モジュール 非同期 IO select/poll などの標準的な仕組み kequeue, epoll, IOCP のような OS ごとの仕組み selectors モジュールは様々な OS 向けの非同期 IO の仕組みを 共通のインターフェイスで使えるようにしたラッパー Atsushi Odagiri async/await の向こう側
  • 34. はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お selectors モジュールを使う処理 監視対象を登録する register ポーリングしてイベントを取得 select 監視を解除 unregister Atsushi Odagiri async/await の向こう側
  • 35. はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お 非同期 IO をコルーチンで処理する イベントループ内でポーリングする Atsushi Odagiri async/await の向こう側
  • 36. はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お 素朴な echo サーバー accept したらそのまま echo 処理を行う 1 つのクライアントの処理が終わらないと他のクライアント の接続を処理できない sock = socket.socket() sock.bind(('localhost', 1234)) sock.listen(100) while True: conn, addr = sock.accept() while True: data = conn.recv(1000) if data: conn.send(data) else: conn.close() break Atsushi Odagiri async/await の向こう側
  • 37. はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お マルチスレッドな echo サーバー accept したら子スレッドを作成してクライアントソケットを 渡す def accept(conn: socket.socket): try: data = conn.recv(1000) while data: conn.send(data) data = conn.recv(1000) finally: conn.close() while True: conn, _ = sock.accept() threading.Thread(target=accept, args=(conn,)).start() Atsushi Odagiri async/await の向こう側
  • 38. はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お スレッドプールを使う echo サーバー accept したらクライアントソケットをスレッドプールに渡す executor = ThreadPoolExecutor() while True: conn, _ = sock.accept() executor.submit(accept, conn) Atsushi Odagiri async/await の向こう側
  • 39. はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お selector にコールバックを使って echo サーバー コールバック処理 def accept(sock, _): conn, addr = sock.accept() # Should be ready print('accepted', conn, 'from', addr) conn.setblocking(False) sel.register(conn, selectors.EVENT_READ, read) def read(conn, _): data = conn.recv(1000) # Should be ready if data: print('echoing', repr(data), 'to', conn) conn.send(data) # Hope it won't block else: print('closing', conn) sel.unregister(conn) Atsushi Odagiri async/await の向こう側
  • 40. はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お selector にコールバックを使って echo サーバー selector や socket の準備 sel = selectors.DefaultSelector() sock = socket.socket() sock.bind(('localhost', 1234)) sock.listen(100) sock.setblocking(False) sel.register(sock, selectors.EVENT_READ, accept) while True: events = sel.select() for key, mask in events: callback = key.data callback(key.fileobj, mask) Atsushi Odagiri async/await の向こう側
  • 41. はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お selector をコルーチンで呼び出せるようにして echo サー バー (1) recv をコルーチンで扱えるようにする def read_async(conn:socket.socket): f: Future[bytes] = Future() def callback(conn: socket.socket, _): sel.unregister(conn) f.done(conn.recv(1000)) sel.register(conn, selectors.EVENT_READ, callback) return f.get_result() Atsushi Odagiri async/await の向こう側
  • 42. はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お selector をコルーチンで呼び出せるようにして echo サー バー (2) send をコルーチンで扱えるようにする def send_async(conn:socket.socket, data: bytes): f: Future[int] = Future() def callback(conn: socket.socket, _): sel.unregister(conn) f.done(conn.send(data)) sel.register(conn, selectors.EVENT_WRITE, callback) return f.get_result() Atsushi Odagiri async/await の向こう側
  • 43. はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お selector をコルーチンで呼び出せるようにして echo サー バー (3) echo タスク def accept(sock, _): conn, _ = sock.accept() conn.setblocking(False) create_task(read(conn)) def read(conn: socket.socket): while True: data = yield from read_async(conn) if data: yield from send_async(conn, data) else: break conn.close() Atsushi Odagiri async/await の向こう側
  • 44. はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お selector をコルーチンで呼び出せるようにして echo サー バー (4) selector やソケットの準備 sel = selectors.DefaultSelector() tasks: typing.List[typing.Generator[None, None, None]] = [] sock = socket.socket() sock.bind(('localhost', 1234)) sock.listen(100) sock.setblocking(False) sel.register(sock, selectors.EVENT_READ, accept) Atsushi Odagiri async/await の向こう側
  • 45. はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お selector をコルーチンで呼び出せるようにして echo サー バー (5) イベントループ while True: events = sel.select() for key, mask in events: callback = key.data callback(key.fileobj, mask) removing: typing.Set[typing.Generator[None, None, None] for t in tasks: try: t.send(None) except StopIteration: removing.add(t) except Exception as e: print(e) Atsushi Odagiri async/await の向こう側
  • 46. はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お おまけ Atsushi Odagiri async/await の向こう側
  • 47. はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お コルーチンでない awaitable class AwaitableSample: def __await__(self): yield return "hello" Atsushi Odagiri async/await の向こう側
  • 48. はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お コルーチンでない! タスクが受け取るのはコルーチンであって awaitable 全般 ではないらしい asyncio.create_task(AwaitableSample()) TypeError: a coroutine was expected, got <__main__.AwaitableSample object at 0x7f4429c36100> Atsushi Odagiri async/await の向こう側
  • 49. はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お まとめ Atsushi Odagiri async/await の向こう側
  • 50. はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お まとめ コルーチン yield で処理を明け渡す協調スレッド (コルーチン) yield from はコルーチンを起動して終了を待機する タスクは起動したコルーチンと結果を受け取る Future の組 非同期 IO OS ごとに異なる方法で IO の状態を監視 ポーリングして状態チェック クライアント接続ごとにスレッドを消費しない 状態が変化するまでコルーチンで待つ Atsushi Odagiri async/await の向こう側
  • 51. はじめに async/await と asyncio コルーチンとは? タスク!future!コルーチンを利用するためのツール 非同期 IO お 参考文献 PEP 255 – Simple Generators PEP 380 – Syntax for Delegating to a Subgenerator -PEP 492 – Coroutines with async and await syntax PEP 3156 – Asynchronous IO Support Rebooted: the “asyncio” Module Python3.4 当時の asyncio リファレンス Atsushi Odagiri async/await の向こう側