世界を動かす技術を、日本語で。

フリースレッドPythonの初年度

概要

  • CPython 3.14.0b1 のリリースと PyCon 2025 開催が、free-threaded Python実現の重要な節目となることを説明。
  • Quansightチームが free-threadedビルド の実験的利用を現実のワークフローで可能にした経緯を紹介。
  • GIL無効化 によるパッケージの課題やエコシステム全体の現状を整理。
  • 主要パッケージやコアモジュールへの スレッドセーフ化対応 の進捗を列挙。
  • 今後の課題・貢献方法・コミュニティへの参加を呼びかける。

Free-threaded Pythonの1年:Quansightとエコシステム対応の最前線

Free-threaded Pythonの意義と課題

  • CPython 3.14.0b1 リリースと PyCon 2025 開催は、free-threaded Python実現に向けた重要な節目となることを確認。
  • Quansightチームは、 free-threadedビルド を複雑な依存関係を持つ実運用ワークフローで試験的に利用可能にすることに貢献。
  • free-threaded Python により、マルチコアCPUやGPUの計算資源を最大限活用できることを強調。
  • GIL有効時 は並列アルゴリズム活用に制約があり、threadingモジュールの利用は限定的であることを説明。
  • multiprocessing はプロセス生成やデータコピーコストが高く、マルチスレッドプログラムの利点が活かせないことを指摘。
  • ネイティブコードを含むパッケージは、 free-threadedビルド 対応にあたりスレッドセーフ性の監査が必須となることを強調。
  • GIL無効化 はCPythonインタプリタの構造的な大改修を伴い、既存パッケージの構造的な修正も必要となることを説明。
  • C拡張内のグローバル状態利用は、 GIL無効時 にはデータ競合を引き起こす危険があることを確認。
  • threadingモジュール 利用時にも理論上はスレッドセーフ問題が発生しうるが、GILにより多くは表面化しなかったことを補足。
  • free-threadedビルド ではこうした問題の顕在化と修正が急務となることを明示。

主な成果と対応パッケージ

  • QuansightとMeta Pythonランタイムチームは、多数のパッケージ・プロジェクトで free-threaded Python対応 を推進。
    • meson, meson-python, setup-python GitHub Actions, packaging, pip, setuptoolsなどの ビルド・ワークフロー系ツール 対応。
    • Cython, pybind11, f2py, PyO3などの バインディング生成ツール 対応。
    • NumPy, SciPy, PyArrow, Matplotlib, pandas, scikit-learn, scikit-imageなどの PyData基盤パッケージ 対応。
    • Pillow, PyYAML, yarl, multidict, frozenlistなどの PyPI主要依存パッケージ 対応。
  • 現在もCFFI, cryptography, PyNaCl, aiohttp, SQLAlchemy, grpcio, safetensors, tokenizersなど 未対応パッケージ への対応を進行中。
  • QuansightチームのCPythonコア開発者は、以下の 主要改善 に貢献:
    • warningsモジュールの デフォルトスレッドセーフ化 (free-threadedビルド)、GIL有効時もオプションで有効化可能。
    • asyncioの スレッドセーフ問題修正 と、スレッドプールランナー利用時の並列スケーリング性能向上。
    • ctypesモジュールの スレッドセーフ化刷新
    • free-threadedガーベジコレクタの 性能向上
    • deferred reference countingスキームの実装支援。
    • adaptive specializing interpreterの最適化、free-threaded CPython 3.14の シングルスレッド性能向上
    • 多数のバグ修正・スレッドセーフ化改善を実施。
  • free-threaded Python対応ガイド を執筆し、今後のパッケージ対応の参考資料として公開。

エコシステムの現状と進捗

  • 1年前の Python 3.13.0b1 時点では、free-threadedビルドでほぼ全てのパッケージがビルド不可状態だったことを説明。
  • 問題の多くは 根本的な障害 ではなく、デフォルトオプションや軽微な前提の破綻によるものだったことを指摘。
  • パッケージメンテナやコミュニティと連携し、多数の問題を解消し、現状は大幅に改善されたことを報告。
  • Cython 3.1.0 のリリースによる公式free-threaded対応が、ビルド問題の大きな解決策となったことを説明。
  • 依然として 未対応のコンパイル済みコード含有パッケージ への対応を継続中。
  • 進捗は 手動更新のステータステーブル やHugo van Kemenadeの 自動トラッカー で確認可能。

現在の課題と今後の展望

  • free-threaded Pythonビルド は実験利用に十分な状態であり、実際のワークフローでの性能・バグ報告が求められていることを呼びかけ。
  • multiprocessing利用時のコスト削減や 並列性能向上 が期待できる一方、多くのパッケージで スレッドセーフ監査 が必要。
  • 多くのPythonライブラリは ミュータブルなデータ構造 を提供しており、スレッドセーフ・マルチスレッド性能に関するドキュメントが不十分であることを指摘。
  • 大規模なレガシーパッケージでは、対応のためのリソースや知見が不足しているケースが多いことを課題として挙げる。
  • コミュニティ全体で依存ツリーの問題を把握し、 持続可能な保守体制 構築を目指すことの重要性を強調。

貢献方法とコミュニティへの参加

  • free-threadedガイド のコントリビューションガイド参照を推奨。
  • Quansight-Labs GitHub orgの free-threaded-compatibilityリポジトリ でエコシステム全体の課題をトラッキング・ガイド執筆を実施中。
  • コミュニティDiscord も開設し、free-threadedビルド対応の議論・協力を促進。
  • 興味がある場合はぜひ参加・協力することを推奨。
  • PyConでの 発表 も予定しており、YouTube録画が今後の学習資源となることを期待。
  • free-threadedビルド がPython言語の未来であり、今後数年で日常的に使われるパッケージ群の性能向上に寄与することを展望。

Hackerたちの意見

PythonがGILを失う日が来るのがちょっと怖いのは俺だけかな?Pythonの開発者たちは、自分たちが何を求めているのか分かってないと思う。どんな言語でも複雑なマルチスレッドコードはあまり信頼できないし、特にPythonのような動的な言語では一番信頼できないよ。

GILがあるかないかは、マルチコアのワークロードを実行したい人だけの心配事だよ。もしまだコードをスレッドやマルチプロセスで動かすことに時間を使っていないなら、実際にはほとんど変わらない。GILに関係なく考えなきゃいけないレースコンディションの問題は、元々存在してるからね。

君の不安を増やしたくはないけど、LLMはGILが存在する前提で何十年分のPythonコードで訓練されていることも忘れないでね。

より現実的に言うと、ML/AIのシーンで起こったように、知識のある人たちが複雑なライブラリを書いて、それを科学者や経験の少ない、リスクを避けたい開発者たちに渡すことになると思う(それ自体は悪いことじゃない)。Pythonが長年にわたって得たクリティカルマスのおかげで、GILは場合によってはかなり厄介なボトルネックになる。だからこそ、俺はGoを学ぶことにしたんだ。C/C++より高レベルだけど、Pythonよりは低レベルで、Pythonではできないことができる適切にスレッド化された(そしてグリーンスレッド化された)プログラミング言語だよ。コンパイルも理由の一つだけど、スレッドに関しては二次的な理由だね。

変化を恐れているのは君だけじゃないし、ちょっと変化に抵抗があるのも分かるよ。ここでの問題は、その恐れの理由があまり合理的じゃないってことだと思う。それに、広いコミュニティの関心は技術的負債に対処することだからね。GILは純粋な技術的負債だよ。30年前は正当化できたけど、20年前はちょっと不格好で、今では世界中がAIのデータ処理をPythonでスケールさせている中で、もううんざりで恥ずかしい存在になっている。プラットフォームの将来を見据えるためには、GILは取り除かれるべきだった。君にとって何が変わるかって?スレッドを使い始めない限り、何も変わらないよ。多分、スレッドを使ってなかったんじゃないかな。Pythonでスレッドを使う意味はほとんどないからね。ほとんどのPythonコードベースはスレッドモジュールを完全に無視して、代わりにノンブロッキングIOや非同期処理などを使っている。GILの問題は、実際にスレッドを使う場合にだけ影響してくる。スレッドを使わないなら、GILを取り除いても何も変わらないよ。壊れるコードなんてないし、スレッドセーフじゃないCライブラリもまだシングルスレッドのままだよ。今スレッドを使い始めたら、注意が必要になるだけだ。もちろん、スレッド化されたPythonコードもあって、ちょっとナイーブに書かれていて、速くなることを期待しているけど、実際にはGILに引っかかっていて、実質的にシングルスレッドになっているものもある。そのコードは今、少し速く動くかもしれないし、ナイーブなスレッドコードはバグが多いから、バグも増えるだろうね。でも、君の不安を解消するためのシンプルな解決策は、スレッドを使わないことだよ。大丈夫だよ。もしくは、スレッドの使い方を学ぶことだね。今ややっとできるようになったし、正しい抽象化があればそんなに難しくないよ。将来的にはそういうものが続々と出てくると思う。構造化された同時実行は、コミュニティの中の何人かにとっては高い優先事項だろうね。

スレッドを使うためにfork()しなきゃいけない最後の言語を使ってるなんて、きっと嬉しいだろうね。結局、消費者向けのマルチコアプロセッサが登場してから20年しか経ってないからね。

これはよくある間違いで、非常に悪く伝えられているね。GILはPythonのコードをスレッドセーフにしない。内部のCPythonの状態を保護するだけなんだ。今日のマルチスレッドのPythonコードはスレッドセーフじゃないよ。

あなた一人じゃないよ。デビッド・バロンのメモは確かに当てはまるね:https://bholley.net/blog/2015/must-be-this-tall-to-write-mul... こういう作業のために考案された言語では、思ったほど簡単じゃない。ほとんどの言語では、意味がまったくないナンセンスを書いてしまうことになる。実験によると、人間は非自明なプログラムを成功裏に理解できないことが分かっていて、Sequential Consistency(順序一貫性)を示さないと理解できないんだ。つまり、すべての出来事が特定の順序で起こるかのように理解できる必要があるんだ。これは機械の動作の現実ではないけど、そうでないと人間のプログラマーは「え、わからないな、全部コンピュータのことかな?」って感じになっちゃう。ほとんどの言語では、この要件を満たさない並行プログラムを書くのはすごく簡単だけど、デバッグしたり、何をしているのかを考えたりすることができないから、災害だよ。私の理解では、GILなしのPythonはSCを失うプログラムをもっと可能にするだろうね。

最悪のケースは、まるで「Python4」のようになるかもしれないね:人々が非GILにアップデートしようとすると壊れるから、数十年も古いバージョンのままでいることになる。

どんな依存関係を考えてたの?Pythonではいろんな呼び出しがGILを解放するから、ロックが必要だし、ほとんどの言語と同じようにレースコンディションもあるよ。JSみたいにコードが「await」するまで順番に実行されるってわけじゃないからね。GILを取り除くことの課題は完全には理解してないけど、C拡張に関することだと思ってた。ほとんどのユーザーが直接心配することじゃないと思うけど。

良いエンジニアリングデザインってのは、不均衡なトレードオフをすることなんだよね。低コストで大きなリターンを得るためにさ。こういう決断は意見が分かれることが多くて、重要なケースでたくさんの利益を得るために、いくつかのエッジケースにはノーと言わなきゃならない。俺が学んだ教訓の一つは、良いデザインは人気やそれに伴う官僚主義には耐えられないってこと。時間が経つにつれて、人々は明確に避けたケースをやれってリクエストをどんどん寄越してくるんだよね。お前が彼らの仕事を妨げていて、現実的じゃないってさ!結局、彼らのために擁護する人はいなくなる。コミュニティにはもっとリソースがあって、もう少し複雑さを受け入れられるってのも一因だけど、だからこそ俺は小さいコミュニティのツールが好きなんだ。

次のパフォーマンスの時代に向けて、これは本当に重要な基盤だね!

GILを取り除くことは、マルチスレッドのPythonコードに他にどんな影響を与えるの?(並行して実行できること以外で)俺の理解では、GILがここまで残っているのは、マルチスレッドのPythonがそれに依存しているからじゃなくて、取り除くことが: - インタープリタの実装を複雑にする - C拡張を複雑にする - シングルスレッドのコードを遅くする からだと思う。マルチスレッドのPythonコードは、すでに任意の2つのバイトコード命令の境界でプリエンプトされる可能性があることを前提にしなきゃいけない。フリースレッドのPythonは同じ保証を提供するのか、それともマルチスレッドのPythonを異なる書き方にしなきゃいけないのか、例えば追加のロックを使う必要があるのか?

フリースレッドのPythonは同じ保証を提供するのか?ほとんどの場合そうだよ。ただ、「任意の2つのバイトコード命令の境界でプリエンプトされる可能性がある」というバグは、フリースレッドがないと本当にヒットしにくいんだ。フリースレッドがないと、人々はあまりスレッド関連のものを使わなくなるから、自然とバグが増えるんだよ。さて、俺の愚痴:> マルチスレッドのPythonコードに他にどんな影響を与えるの?それは人々がマルチプロセスのワークアラウンドを使うのを止めさせるから、ユーザーコードを簡素化するんだ。個人的には、インタープリタをより複雑にする価値は十分にあると思う。> C拡張を複雑にする 代替手段(サブインタープリタ)は、フリースレッドよりもC拡張を複雑にするし、エコシステム全体で最も重要なC拡張であるnumpyは、サブインタープリタをサポートしたくないと言っている。逆に、彼らはすでに今日フリースレッドをサポートしていて、残りのバグを積極的に解決しているよ。> シングルスレッドのコードを遅くする それがトレードオフだね。個人的には、シングルスレッドのコードが一桁パーセント遅くなるのは価値があると思うよ。

あなたの理解は正しいよ。全てのコアを使えるけど、スレッドごとの速度はかなり遅くなるし、既存のライブラリも手直しが必要かもしれない。PyTorchで試してみたけど、半分の作業をするのに10倍のCPUを使った。これらの問題は改善されると思うけど、20年もこれを待ってたから、進展が見られて嬉しいね。

レースコンディションが発生しやすくなるから、マルチスレッドのPythonは同じレベルの信頼性を達成するためにもっと注意深く書かれる必要があるね。

そうだね、エコシステムのすべての部分が複雑になって、バグが発生しやすくなるのに、スクリプト言語でパフォーマンスを上げようとしてるんだ。

私はPythonユーザーだけど、専門家とは程遠いよ。たまに「concurrent.futures」を使って、すごくシンプルな関数を同時に実行させることがあるんだけど、「concurrent.futures」ユーザーにはどんな影響があるのかな?これから何を変えればいいんだろう?

スレッドがGILでロックされないから、速くなるはずだよ。共有オブジェクトを正しくロックしているか、そもそも使っていないなら、大丈夫だと思うよ。

ただのAI画像だって分かってるけど、二つの尾を持つヘビ?ちょっと待ってよ!

コンフュソボラス

シーッ。大きな声で文句言わないで、重要なヒントを失っちゃうから。蛇のイラストを使ったPythonの記事は、だいたい無視してもいいよ。だって、あんまりわかってないから。 -- Python, モンティ

ところで、マイクロソフトが全速力のPythonチームを解散させたらしいよ。2025年の収益がチームを維持するには足りなかったみたい。https://www.linkedin.com/posts/mdboom_its-been-a-tough-coupl... CPythonにどんなパフォーマンス改善が残るか見てみよう、他の企業がその作業を支援しない限りね。Facebook(名前を訂正する必要はないよね)がまだその一部を支援してると思うけど。

「Facebook」って言っただけで気にしなかったと思うよ。多分、気づかなかったかも。でも、なんで「Facebook」って書いたのに、その後問題に気づいて、「Meta」に変える代わりに、長い「(名前を訂正する必要はない)」を付け加えたのかすごく気になる。何か特別な意図があるの?

ああ、それは本当に悲しいね。彼らは受け入れて拡張したみたいだけど、残されたことは一つだけだね。

彼らは5年前に約束されたスケジュールからかなり遅れているね。それに、この段階で深刻な政治的・ガバナンスの問題がマイクロソフトに気づかれないわけがないと思う。優秀なマイクロソフトの社員は、自分の専門知識をCPythonに提供したくないだろうし、後で数人の選ばれた平凡な人たちからグループ名誉毀損を受けるのは嫌だろうね。CPythonは過剰な約束をして、従順で忠実な人に仕事を割り当て、優秀な異議申し立て者を排除する組織なんだ。昔はそんなことなかったのに。問題は完全に自業自得だよ。

残念だけど、Microsoftがこの取り組みに長期的にコミットすると言っていたときに、私はそうなるだろうって言ってたんだよね。

Googleは昨年、Python開発チーム全体を解雇したんじゃなかったっけ?両方の背後に何か動機があるのかな。

ヘッダー画像のヘビは、二つの尾の先があるように見えるね…

同じプロセス内で2つ目のスレッドが生成されたんじゃないかな。

代わりに、多くの人がマルチプロセッシングを使おうとするけど、プロセスを生成するのは高コストだね。賛成。> そして、プロセス間で通信するには高価なデータのコピーを作る必要があることが多い。SharedMemory [0] があるよ。これがもっと使われない理由が理解できない。ShareableListもあって、まさにその名の通りのことをするんだけど、すごく便利だよ。[0]: https://docs.python.org/3/library/multiprocessing.shared_mem...

[フラグ付き]

ShareableList では、任意の構造化されたオブジェクトを共有できないよ。共有できるのは原子スカラーとバイト/文字列だけ。インスタンス間で構造化されたPythonオブジェクトを共有したいなら、pickle.dump/pickle.load のコスト(プロセス間通信のCPUオーバーヘッド)と、プロセス内での複製されたオブジェクトのメモリコストを支払わなきゃいけない。

うん、私はこの方法でnumpy配列を共有するのに大成功してるよ。明示的な共有は大した負担じゃないし、スレッド間で物を誤って共有したときに発生する問題をデバッグする難しさと比べれば特にね。人々はスレッドの利点をマルチプロセスよりも過大評価してるし、GILを無効にするライブラリエコシステムが準備できていない中で、これから起こるランダムなセグフォルトをデバッグするのが待ち遠しくないな。JavaScriptが共有スレッドを持っていないことについて、みんながそんなに文句を言わなかったのはなぜだろう。多分、JavaScriptが速すぎて、あまり手を伸ばさなくて済むからかな。Pythonのベースラインパフォーマンスにもっと努力が注がれてほしいな。

プロセスを生成するのは、一般的にUnixでは1ms未満で済むよ。PYTHONインタープリタプロセスを生成するのには、インポートの数によっては30msから300msかかることもあるけど、これはmain()に到達するまでの時間だよ。1桁から2桁の違いがあるから、正確に言う価値があるね。これはCGIに関する誤解だよ。C、Rust、GoでのCGIはうまく動くからね。例えば、sqlite.orgはリクエストごとにプロセスを実行してるよ - https://news.ycombinator.com/item?id=3036124

[死んでる]

プロセスは独立して死ぬことがあるから、ロックをかけている間にプロセスが死んだときの共有メモリデータ構造の状態を管理するのは難しいことがあるんだ。Postgresは共有メモリデータ構造を使ってるから、こういう状態から完全に回復できないときは、すべてのバックエンドプロセスを殺さなきゃいけないこともある。一方で、スレッドが独立して死んだときのことを考える人はいないよね、だって失敗の仕方が一緒だから。

共有メモリは専用ハードウェアでしか動かないよ。AWS Fargateみたいな環境で動かしてると、共有メモリはないから、ネットワークやファイルシステムを使わなきゃいけなくて、遅延がすごく増えるんだ。プロセスを立ち上げるよりもずっと遅いよ。フォークでプロセスをコピーするのは全然違う問題だし、俺の経験ではグリーンスレッドやアクターモデルの方がずっと進むと思う。

なんでこれがもっと頻繁に使われないのか、全然理解できない。JSONシリアライズ可能なデータ構造(リスト、辞書、文字列、数字)をSharedMemoryに入れられるの?ランダムなPythonクラスの通常のインスタンスはどうなの?もし答えが「いいえ」なら、それがあまり使われない理由を説明してるよね。ドキュメントの例ではバイト文字列やバイト配列をやり取りしてるみたいだけど、普通のデータ構造よりずっと不便だよ。

こんにちは、私は20年間プロとしてPythonを使って開発してきたので、ちょっと意見を言いたいと思います。 decent threadingは素晴らしいニュースですが、実際にはごく少数のユースケースにしか影響しません。スレッドはメッセージパスが難しいときにのみ厳密に必要です。最近のPythonエコシステムには、そういったケースに対するプレイブックソリューションが用意されています。スレッドの複数の大きな落とし穴(つまり、ロック)を考えると、特定のライブラリやドメインでしか役に立たないものになる可能性が高いです。それに、バニラPythonが大好きですが、CPUの性能を最大限に引き出したい人(実際にはメモリ帯域幅)には、ネイティブコードで書かれたオフ・ザ・シェルフのライブラリがたくさんあります。(Pypyやnumbaなども honorable mentionです)。最後に、Pythonでの劇的なパフォーマンス革新はasyncプログラミングでした。これに不慣れな人にはぜひ見てみることをお勧めします。

私もあなたほど長く使ってないけど、あなたが言ってることにはほとんど同意するよ。ただ、私はちょっと違った見方をしてるかな。Pythonにはスレッドを避けるためのしっかりしたワークアラウンドがたくさんあるよ。今までのPythonのスレッドは本当にひどかったからね。CPUバウンドのワークロードを2倍速くしようと無邪気に使おうとしたけど、GILの影響をすぐに理解して、そのコードは全部捨ててマルチプロセスにしたんだ。それもまた大変で、大きなデータ構造をシリアライズして渡さなきゃいけなかったから、2倍のコアで約1.5倍の速度と、サーバールームがちょっと暑くなっただけだった。Pythonに良いスレッドサポートがあればいいな。いつも正しい解決策とは限らないけど、絶対に素晴らしい状況がたくさんあるし、今はその欠如を避けるために代替アプローチのプレイブックでごまかしてるんだ。でも、意味があるときにはasyncを使ってね。それは美しいものだから。(そう、Glyph、私たちは「だから言ったじゃん!」って声が聞こえるよ。あなたは正しかった。)

こういうスレッドがいつも、スレッドを使わない方がいいっていう狂った議論に発展するのが嫌だな。実際にPythonコードの高速化を試みたことがある人たちは、プロセスの制限が多すぎて、オブジェクトをピクル化しなきゃいけなかったり、クラウド環境でフォークがうまくいかなかったり、アプリケーションによってはスパーンがすごく遅かったりすることに気づいてるから、共有メモリを持った適切なスレッドがあればどれだけ素晴らしいかって思ってるんだ。プロセスの使用はずっと重くて、わかりにくいよ。