
この記事は、インテルのウェブサイトで公開されている「Needle and Thread – An Easy Guide to Multithreading in Python*」の日本語参考訳です。原文は更新される可能性があります。原文と翻訳文の内容が異なる場合は原文を優先してください。
Python スレッド化のジレンマを解消する
Python は、特に AI やマシンラーニング (ML) の開発において強力な言語です。しかし、CPython (プログラミング言語のオリジナルのリファレンス実装およびバイトコード・インタープリター) はマルチスレッド化されていません。マルチスレッド機能と並列処理を有効にするには、内部でのサポートが必要です。NumPy、SciPy、PyTorch などのライブラリーは、C ベースの実装を利用して、必要なマルチコア処理の一部を有効にします。悪名高い Global Interpreter Lock (GIL) は、CPython インタープリターを、シングルスレッド環境かマルチスレッド環境かに関係なく、一度に 1 つのスレッドでのみ機能するように「ロック」します。
要点: Python はシングルスレッド・プログラムの実行に優れていますが、マルチスレッドやマルチプロセスが必須または優先される状況には適していません。
別の視点から Python を見てみましょう。
Vanilla Python を 1 本の針、GIL を 1 本の糸として想像してみてください。その針と糸でシャツを作成します。出来上がったシャツは素晴らしい品質ですが、同じ品質を維持しながら、より効率良く作成する方法があるかもしれません。oneAPI プログラミング・モデルや Numba のライブラリーなどを使用して Python アプリケーションを並列化することで、その課題に対応できます。1 本の針と 1 本の糸の代わりにミシンを使用し、1 台ではなく、数十台または数百台のミシンを使用して、記録的な速さで多数のシャツを作成します。
これが、インテル® アーキテクチャーの命令セットを最適化する高性能パッケージのセットである、インテル® ディストリビューションの Python の強力なライブラリーとツールの目標です。
Python のオーバーヘッドを低く抑え、数学およびスレッド処理に oneAPI ライブラリーを使用して高速化し、NumPy、SciPy、Numba などの計算負荷の高い Python 数値演算および科学パッケージで、C++ プログラムに近いパフォーマンス・レベルを達成できるよう開発者を支援します。これにより開発者は、アプリケーションのマルチスレッド化、ベクトル化、メモリー管理を効率良く行うことができ、同時にクラスター全体で効果的なスケーリングを達成できます。1
Python のコンポーザビリティーと並列性を向上させるインテルのアプローチと、それが AI/ML ワークフローの高速化にどのように役立つかについて、さらに深く掘り下げてみましょう。
入れ子の並列処理: NumPy と SciPy
NumPy と SciPy は、それぞれ数値処理と科学計算向けに設計された Python ライブラリーです。
Python プログラムをマルチスレッド化/並列化する 1 つの方法は、最も外側のループを並列化したり、アプリケーション・レベルで関数やパイプラインを並列化して、プログラムの可能なすべてのレベルで並列処理を利用することです。Dask、Joblib、組込みマルチプロセシング・モジュール mproc (ThreadPool クラスを含む) などのライブラリーは、この並列化に役立ちます。
AI および ML アプリケーションでビッグデータを処理する場合、NumPy や SciPy などの Python モジュールを使用してデータ並列処理を実現できます。これらのモジュールは、インテル® oneAPI マス・カーネル・ライブラリー (インテル® oneMKL) などの最適化された数学ライブラリーにより高速化できます。インテル® oneMKL は、マルチスレッド・ランタイムを使用してマルチスレッド化されています。スレッドレイヤーは、環境変数 (MKL_THREADING_LAYER) を介して制御できます。2
これにより、1 つの並列領域が関数を呼び出し、その中にさらに別の並列領域があるというコード構造 (入れ子の並列処理) が実現します。この並列処理内の並列処理は、NumPy および SciPy ベースのプログラムでは通常避けられない同期レイテンシーとシリアル領域 (つまり、並列実行できない領域) を最小限に抑える、または隠蔽する効率的な方法です。
さらに先へ: Numba
NumPy と SciPy は数学とデータに特化したさまざまなアクセラレーションを提供しますが、それらは C 拡張機能により高速化された数学処理の固定セットです。しかし、開発者は非標準の数学処理を使用する必要があるかもしれません。そして、C 拡張と同等の速度を期待するかもしれません。その場合、Numba を利用できます。
Numba は、LLVM ベースの「ジャスト・イン・タイム」 (JIT) コンパイラーとして機能し、Python と C/C++ のような静的に型付けされたコンパイル言語との間のパフォーマンス・ギャップを埋めます。また、インテル® oneAPI スレッディング・ビルディング・ブロック (インテル® oneTBB)、OpenMP、workqueue など、複数のスレッドランタイムをサポートしています。これらの 3 つのランタイムに対応する 3 つの組込みスレッドレイヤーがあります。デフォルトで存在するスレッドレイヤーは workqueue のみですが、ほかのレイヤーは conda コマンド (例: $ conda install tbb) を使用して簡単にインストールできます。スレッドレイヤーは、環境変数 NUMBA_THREADING_LAYER で設定できます。スレッドレイヤーは次のいずれかの方法で選択する必要があります: (1) さまざまな並列実行形式で一般的に安全なレイヤーを選択する、または (2) スレッドレイヤー名 (例: tbb) を明示的に指定する。Numba スレッドレイヤーの詳細については、Numba の公式ドキュメント (英語) を参照してください。
スレッド・コンポーザビリティー
アプリケーションまたはそのコンポーネントのスレッド・コンポーザビリティー (構成可能性) は、共存するマルチスレッド・コンポーネントの有効性や効率性を決定します。「完全に構成可能な」コンポーネントは、それ自体の効率性またはシステム内の他のコンポーネントの効率性を損なうことなく機能します。
完全に構成可能なスレッドシステムを目指すには、過剰な数のスレッド (オーバーサブスクリプション) を生成しないようにする必要があります。つまり、実行に特定の数のスレッドを必要とする「必須」並列処理を、どのコンポーネントまたはコードの並列領域も必要としないことを保証しなければなりません。
代替案は、ワーク・スケジューラーが自動でコンポーネントと並列領域のタスクを調整し、コンポーネントがマップされるスレッドをユーザーレベルで指示する「オプション」並列処理を作成することです。スケジューラーは、単一の共有スレッドプールを使用してプログラム・コンポーネントとライブラリーを配置するため、スケジューラーのスレッドモデルの効率は、ハイパフォーマンス・ライブラリーの組込みスキームを上回る必要があります。そうでない場合、効率によるメリットが得られません。
インテルのコンポーザビリティーと並列処理へのアプローチ
インテル® oneTBB をワーク・スケジューラーとして使用することで、スレッド・コンポーザビリティーを容易に実現できます。インテル® oneTBB は、マルチコア並列処理を可能にするオープンソースのクロスプラットフォーム C++ ライブラリーであり、スレッド・コンポーザビリティーとオプションの入れ子の並列処理を考慮して設計されています。
この記事の執筆時点で最新のインテル® oneTBB バージョンでは、複数のライブラリー間でスレッド・コンポーザビリティーを有効にして Python のマルチスレッド・パフォーマンスを向上する実験的なモジュールが利用可能になりました。この高速化は、前述のように、スケジューラーの強化されたスレッド割り当てによってもたらされます。
インテル® oneTBB は、標準の Python ThreadPool (英語) に代わる Pool クラスを使用します。また、モンキーパッチ (英語) を使用して実行時にオブジェクトを動的に置き換えたり更新することで、コードを変更することなくモジュール全体でスレッドプールが有効になります。さらに、インテル® oneTBB は インテル® oneMKL の代わりに独自のスレッドレイヤーを有効にして、NumPy および SciPy ライブラリーからの呼び出しで自動的に構成可能な並列処理を提供します。
入れ子の並列処理によってパフォーマンスがどの程度向上するかをテストするには、インテル® oneMKL を利用した NumPy、インテル® oneTBB、対称型マルチプロセシング (SMP) モジュールと、対応する IPython カーネルがインストールされたシステムで実行する、次のコンポーザビリティー・デモのサンプルコードを参照してください。IPython は、複数のプログラミング言語で対話型コンピューティングを行う機能豊富なコマンド・シェル・インターフェイスです。このデモは、定量性能を比較するため Jupyter Notebook 拡張機能を使用して実行されました。
import NumPy as np
from multiprocessing.pool import ThreadPool
pool = ThreadPool(10)
Jupyter メニューでカーネルを変更する場合、以下で説明するランタイム結果を得るには、上記のセルを毎回再実行して ThreadPool を作成する必要があります。3
次のコードでは、デフォルトの Python カーネルが使用され、3 回とも同じ行が実行されます。
%timeit pool.map(np.linalg.qr, [np.random.random((256, 256)) for i in range(10)])
このアルゴリズムをデフォルトの Python カーネルで使用して、行列の固有値を検索できます。Python-m SMP カーネルを有効にすると、実行時間が大幅に改善されます。Python-m TBB カーネルを使用すると、さらに大きな改善が得られます。
このコンポーザビリティー・デモでは、インテル® oneTBB の動的タスク・スケジューラーにより、最高のパフォーマンスを実現します。動的タスク スケジューラーは、最も内側の並列領域がシステムの CPU を最大限に活用できない場合や、処理する作業量が変動する可能性がある場合に、コードを最も効率良く処理します。SMP アプローチも有用ですが、通常、ワークロードのバランスが取れていて、最も外側のすべてのワーカーの負荷が比較的類似している場合に、最高のパフォーマンスを発揮します。
結論: マルチスレッドを活用して AI/ML ワークフローを加速する
AI および ML 指向の Python プログラムの効率を向上させる方法は多数あります。マルチスレッドとマルチプロセシングのパワーを活用することは、今後も、AI/ML ソフトウェア開発ワークフローを限界まで加速し、さらに限界を超えて加速する最も重要な手段の 1 つであり続けるでしょう。インテルの他の AI ツール (英語) やフレームワーク (英語) の最適化をチェックし、インテルの AI ソフトウェア・ポートフォリオ (英語) の基盤である、統一されたオープンな標準ベースの oneAPI プログラミング・モデルについて理解を深めることを推奨します。
ソフトウェアを入手
- インテル® ディストリビューションの Python は、スタンドアロン (英語) またはインテル® oneAPI AI アナリティクス・ツールキット (英語) の一部として利用できます。
- インテル® oneTBB (英語)、インテル® oneMKL (英語) はスタンドアロンまたはインテル® oneAPI ベース・ツールキットの一部として利用できます。
Python サンプルコード
その他の AI サンプルコード (英語)
謝辞:
本ブログに貢献してくれた Sergey Maidanov、Oleksandr Pavlyk、Diptorup Deb に感謝します。
製品および性能に関する情報
1 性能は、使用状況、構成、その他の要因によって異なります。詳細については、http://www.intel.com/PerformanceIndex/ (英語) を参照してください。
最新メジャーバージョン 2025 対応!インテル® ソフトウェア開発ツール向けサポートサービス
エクセルソフトが提供するインテル® ソフトウェア開発ツール向けサポートサービスでは、インテル® ソフトウェア開発ツールの旧バージョンから新バージョンへの移行、CUDA から SYCL へのコード移行、他社製 GPU とのコード互換など、新しい環境でこれまで通り業務を遂行するための移行を支援します。製品の移行に関してお悩み、質問などお気軽にお問い合わせください。
最新のドキュメント日本語参考訳
エクセルソフトでは、バージョン 2025.0 に対応するドキュメントの日本語参考訳を一般公開しています。現在、以下のドキュメントに関する日本語参考訳をご参照いただけます。
- インテル® ソフトウェア開発ツールのリリースノート (ベース・ツールキット、ベース & HPC ツールキット)
- インテル® ソフトウェア開発ツールの製品紹介資料
- インテル® oneAPI DPC++/C++ コンパイラーのリリースノート
- インテル® Fortran コンパイラーのリリースノート
- インテル® VTune™ プロファイラーのリリースノート
- インテル® DPC++ 互換性ツールのリリースノート
- oneAPI for NVIDIA* GPU および AMD* GPU 導入ガイド
- インテル® oneAPI プログラミング・ガイド
インテル® ソフトウェア開発ツール2025 リリース記念キャンペーン
インテル® ソフトウェア開発ツールの最新バージョン 2025 のリリースを記念して、対象のオンラインイベントに参加いただき、事後アンケートにご回答いただいた方の中から、抽選で合計 18 名様にインテル Arc B580 グラフィックスなどが当たるプレゼント・キャンペーンを実施中です。【締切 : 2025年2月20日 (木)】