Upgrade to Pro — share decks privately, control downloads, hide ads and more …

FastAPIでのasync defとdefの使い分け

Takashi Sasaki
September 27, 2024

FastAPIでのasync defとdefの使い分け

Takashi Sasaki

September 27, 2024
Tweet

More Decks by Takashi Sasaki

Other Decks in Technology

Transcript

  1. Copyright © Acroquest Technology Co., Ltd. All rights reserved. PyCon

    JP 2024 DAY1 FastAPIのasync defとdefの使い分け Acroquest Technology株式会社 佐々木 峻 1
  2. CONFIDENTIAL Copyright © Acroquest Technology Co., Ltd. All rights reserved.

    佐々木 峻 Acroquest Technology株式会社 執筆 Interface誌 • 2023年Interface 4月号 ChatGPTについて • 2023年Interface 11月号 ローカルLLMについて • 2024年Interface 8月号 GPU x ローカルLLMについて 開発 • NLP/検索が専門 • LLMを使ったRAGソリューションの開発 資格 • Azure Developer Associate • Azure Data Engineer Associate • Azure Data Scientist Associate
  3. 目次 Copyright © Acroquest Technology Co., Ltd. All rights reserved.

    3 1. Pythonにおける並行処理・並列処理・非同期処理 2. マルチスレッドとasync/await 3. FastAPIでのasync defとdefの違い 4. 検証 5. まとめ
  4. Copyright © Acroquest Technology Co., Ltd. All rights reserved. 4

    前提 CPUは意外と暇 I/Oを待っている間、CPUは何もしてない。暇。 外部アクセス等のI/O処理が多いとき、CPUはその性能をフルに発揮できてない I/O待ち CPU処理 例)DBアクセスが発生するWebサーバの処理 ※I/O待ちが多い処理を「I/Oバウンド」、I/O待ちではなくCPU処理が多い場合 を「CPUバウンド」と呼ぶ。 今回取り上げたいのはI/Oバウンドな処理 サーバ 処理 I/O待ち サーバ 処理 I/O待ち DBアクセス DBアクセス
  5. Copyright © Acroquest Technology Co., Ltd. All rights reserved. 5

    前提2 暇してもらっては困る CPUは明らかに暇なのに、何も効率化しないと、 CPUが忙しくないが利用者は待たされる事態となる Aさんのリクエスト 例)DBアクセスが発生するWebサーバの処理で、1プロセス1コアで何も考えずに処理した場合 このあと説明する並列処理、並行処理、非同期処理などで暇をなくすことが重要! Bさんのリクエスト Cさんのリクエスト サーバ 処理 I/O待ち サーバ 処理 サーバ 処理 I/O待ち サーバ 処理 サーバ 処理 I/O待ち サーバ 処理 待機 さらに待機…
  6. Copyright © Acroquest Technology Co., Ltd. All rights reserved. 6

    Pythonにおける並列処理・並行処理・非同期処理 VS VS 並列処理 並行処理 非同期処理
  7. Copyright © Acroquest Technology Co., Ltd. All rights reserved. 7

    Pythonにおける並列処理・並行処理・非同期処理 VS VS マルチプロセス マルチスレッド async/await Pythonでの実装方法 並列処理 並行処理 非同期処理
  8. CPUコア1 CPUコア1 CPUコア1 それぞれのイメージ Copyright © Acroquest Technology Co., Ltd.

    All rights reserved. 8 並列処理 並行処理 非同期処理 処理 I/O待ち I/O待ち イベントループ マルチプロセス マルチスレッド async/await 処理 I/O待ち 処理 I/O待ち 処理 I/O待ち 処理 処理 処理 CPUコア2 処理 I/O待ち CPUコア3 処理 I/O待ち • 処理をプロセスとして起動 • プロセスごとにCPUコアを割り 当てて同時並列に処理 プロセス1 プロセス2 プロセス3 スレッド1 スレッド2 スレッド3 • 処理をスレッドとして起動 全スレッドは1コアで動作 • I/O待ち中に他のスレッドが処理を 進めることで同時処理 • 1コアで処理を実施 • I/O待ちの開始終了はイベント ループが管理。待ちが終了次第、 空きを見つけて続きの処理を それぞれ実施 処理 処理 処理 処理 処理 処理 処理 処理 処理
  9. Copyright © Acroquest Technology Co., Ltd. All rights reserved. 9

    Pythonにおける並列処理・並行処理・非同期処理 並列処理 並行処理 非同期処理 マルチプロセス マルチスレッド async/await • multiprocessingという 標準ライブラリを利用 Pythonでの 実装 • threadingという 標準ライブラリを利用 • async/await機能を利用 • プロセス自体を分けるので CPUリソースを効率よく 使うことができる メリット • API呼び出しなどのI/O バウンドな処理の場合に 高速化が期待できる。 • 共有リソースの実装などが 比較的容易 • API呼び出しなどのI/O バウンドな処理の場合に 高速化が期待できる。 • プロセス間の値の受け渡し などの実装がやや難しい デメリット • コンテキストスイッチが ありスレッドが増えると 速度が低下する • 非同期処理を利用する時 にはasync/await専用の 実装が必要。
  10. それぞれのイメージ Copyright © Acroquest Technology Co., Ltd. All rights reserved.

    10 なぜスレッドが分かれているのに 順番を待っているのか? CPUコア1 CPUコア1 CPUコア1 並列処理 並行処理 非同期処理 処理 I/O待ち I/O待ち イベントループ マルチプロセス マルチスレッド async/await 処理 I/O待ち 処理 I/O待ち 処理 I/O待ち 処理 処理 処理 CPUコア2 処理 I/O待ち CPUコア3 処理 I/O待ち プロセス1 プロセス2 プロセス3 スレッド1 スレッド2 スレッド3 処理 処理 処理 処理 処理 処理 処理 処理 処理
  11. Pythonにおけるマルチスレッドの罠 Copyright © Acroquest Technology Co., Ltd. All rights reserved.

    11 1. Javaだとスレッドを分けるとコアを複数利用できるが、 Pythonだと1つのコアしか利用できない ⇒Global Interpreter Lock 2. Pythonの処理系の一つであるCPythonなどにある制約 • JythonなどGILがない処理系もあるので、その場合は 今回の話の対象外 3. Pythonでは一つのプロセスが同時に実行できるスレッドは 一つだけ。 4. なので、CPUを多く使う処理ではマルチスレッドにしても マルチプロセスとは違い高速化はしない。 5. 左のようにI/O待ちがある処理では、I/O待ちのときにス レッドを切り替えて処理を進められる。 並行処理 マルチスレッド 処理 I/O待ち 処理 I/O待ち 処理 I/O待ち
  12. それぞれのイメージ Copyright © Acroquest Technology Co., Ltd. All rights reserved.

    12 やっていること同じなのでは? CPUコア1 CPUコア1 CPUコア1 並列処理 並行処理 非同期処理 処理 I/O待ち I/O待ち イベントループ マルチプロセス マルチスレッド async/await 処理 I/O待ち 処理 I/O待ち 処理 I/O待ち 処理 処理 処理 CPUコア2 処理 I/O待ち CPUコア3 処理 I/O待ち プロセス1 プロセス2 プロセス3 スレッド1 スレッド2 スレッド3 処理 処理 処理 処理 処理 処理 処理 処理 処理
  13. マルチスレッドとasync/await Copyright © Acroquest Technology Co., Ltd. All rights reserved.

    13 スレッドの切り替えにもコストがかかる 切り替え時間 並行処理 非同期処理 マルチスレッド async/await 一つのスレッドの中でI/O待ちのときに次 の処理を進めているだけ。 スレッドの切り替えは、async/awaitの処理切替 よりも時間がかかる。(コンテキストスイッチ)
  14. マルチスレッドとasync/await Copyright © Acroquest Technology Co., Ltd. All rights reserved.

    14 スレッドの切り替えにもコストがかかる スレッド数が増えるとasync/awaitに対してマルチスレッドの方が スレッドの切り替え分処理時間が長くなる 切り替え時間 並行処理 非同期処理 マルチスレッド async/await
  15. マルチスレッドとasync/await Copyright © Acroquest Technology Co., Ltd. All rights reserved.

    15 async/awaitは実装に慣れが必要(個人の感想です) 1. これまで同期処理しか書いてこなかったエンジニアからすると最初はなじみづらい。 2. async/awaitを使用する場合、その処理内で呼ばれるメソッドなどはすべてasync/awaitを 意識したコードにする必要があり、ライブラリも対応したものしか使えない。 例)requestsライブラリはasyncに対応していない。
  16. マルチスレッドとasync/await Copyright © Acroquest Technology Co., Ltd. All rights reserved.

    16 async/awaitは実装に慣れが必要(個人の感想です) マルチスレッドの場合
  17. マルチスレッドとasync/await Copyright © Acroquest Technology Co., Ltd. All rights reserved.

    17 async/awaitは実装に慣れが必要(個人の感想です) マルチスレッドの場合
  18. FastAPIにおけるasync defとdefの違い Copyright © Acroquest Technology Co., Ltd. All rights

    reserved. 18 async defは非同期処理、defはマルチスレッド 1. FastAPIはPath Operation関数をdefで書いた場合、リクエストを受けたらスレッドを自動 で起こしてくれる。 2. async defで書かれている場合は、非同期処理にとして扱われるため、スレッドは作成され ない。 defを利用する場合 async defを利用する場合
  19. FastAPIにおけるasync defとdefの違い Copyright © Acroquest Technology Co., Ltd. All rights

    reserved. 19 async defは非同期処理、defはマルチスレッド 1. FastAPIはPath Operation関数をdefで書いた場合、リクエストを受けたらスレッドを自動 で起こしてくれる。 2. async defで書かれている場合は、非同期処理にとして扱われるため、スレッドは作成され ない。 async defの中で同期処理を実装すると、シングルスレッドの同期処理になってしまう
  20. 検証 Copyright © Acroquest Technology Co., Ltd. All rights reserved.

    20 async def+同期処理はどれくらい遅くなるのか 1. OpenAIのAPIにリクエストを投げる処理を例に実験してみる。 2. async def+同期処理とdef+同期処理で実装したAPIに、それぞれに1分間に100リクエスト 送ってレスポンスタイムの推移を比較する 環境 1. クラウド上のLinux VM(vCPU:1, メモリ:1GB, OS: Linux) 2. Python 3.12
  21. 検証 Copyright © Acroquest Technology Co., Ltd. All rights reserved.

    21 async def+同期処理とdef+同期処理のAPIエンドポイントを用意する
  22. 検証 Copyright © Acroquest Technology Co., Ltd. All rights reserved.

    22 応答時間の推移 async def + 同期処理の場合 def + 同期処理の場合
  23. 検証 Copyright © Acroquest Technology Co., Ltd. All rights reserved.

    23 応答時間の推移 async def + 同期処理の場合 def + 同期処理の場合 async def + 同期処理の場合はリクエストを 送るにつれてレスポンスタイムが伸びている ⇒リクエストが前の処理待ちで溜まっている
  24. まとめ Copyright © Acroquest Technology Co., Ltd. All rights reserved.

    24 Pythonにおけるマルチプロセス・マルチスレッド・async/awaitは 処理がCPUバウンドかI/Oバウンドで使い分けるのが良い FastAPIにおけるPath Operation関数のasync defはasync/await、 defはマルチスレッドとして処理される Fast APIのasync def内で同期処理として実装すると、パフォーマンス 問題につながるので、同期処理の場合はdefを使う async defはコンテキストスイッチがない分、マルチスレッドよりも高速 なので、実装さえできれば大量のリクエストをさばきたい場合は有効 1 2 3 4