80

行列の加算、乗算などの単純なタスクを実行するために共有メモリ マシン用の OpenMP を (C と FORTRAN の両方で) コーディングした経験があります (LAPACK と競合する方法を確認するためだけに)。ドキュメントを見なくても簡単なタスクを実行するのに十分な OpenMP の知識があります。

最近、私は自分のプロジェクトで Python に移行しましたが、絶対的な基本以上の Python の経験はありません。

私の質問は:

Python で OpenMP を使用する最も簡単な方法は何ですか? 最も簡単とは、プログラマー側の労力が最も少ないものを意味します (システム時間が追加されたとしても)。

私が OpenMP を使用する理由は、いくつか!$OMPの s が点在するシリアル コードを動作する並列コードに変換できるからです。大まかな並列化を達成するのに必要な時間は驚くほど短いです。この機能を Python で複製する方法はありますか?

SOをブラウジングすると、次のことがわかります。

  • C 拡張機能
  • スタックレス Python

もっとありますか?私の質問に最もよく当てはまるのはどれですか?

4

7 に答える 7

47

シトン

CythonOpenMPをサポートしています。Cython では、prange(並列範囲) 演算子を使用し、 -fopenmpsetup.py にコンパイラ ディレクティブを追加することで、OpenMP を追加できます。

prange スタンザで作業する場合、 を使用してグローバル インタープリター ロック (GIL)with nogil:を無効にするブロックを指定することにより、実行が並列で実行されます。

cython_np.pyxをコンパイルするには、以下に示すように setup.py スクリプトを変更する必要があります。-fopenmpOpenMP を有効にして OpenMP ライブラリとリンクするために、コンパイル中に引数として使用するように C コンパイラに通知するように指示します。

from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
setup(
    cmdclass = {"build_ext": build_ext},
    ext_modules = [
        Extension(
            "calculate",
            ["cython_np.pyx"],
            extra_compile_args = ["-fopenmp"],
            extra_link_args = ["-fopenmp"]
        )
    ]
)

Cython ではprange,、さまざまなスケジューリング手法を選択できます。静的では、ワークロードは使用可能な CPU 間で均等に分散されます。ただし、一部の計算領域は時間的に高価であり、他の領域は安価であるため、Cython にCPU 全体でスタティックを使用して作業チャンクを均等にスケジュールするように依頼すると、一部の領域の結果は他の領域よりも速く完了し、それらのスレッドはその後じっと座っている。ダイナミックガイドの両方スケジュール オプションは、ワークロードの計算時間が変動する場合に CPU がより均等に分散されるように、実行時に動的に小さなチャンクで作業を割り当てることにより、この問題を軽減しようとします。したがって、コードの正しい選択は、ワークロードの性質によって異なります。

ナンバー

Numba のプレミアム バージョンである NumbaPro は、prangeOpenMP を操作するための並列化演算子を実験的にサポートしています。

ピトラン

Pythran (Python のサブセット用の Python-to-C++ コンパイラ) は、Python 2.7 のみを使用して実行されますが、ベクトル化の可能性と OpenMP ベースの並列化の可能性を利用できます。ディレクティブを使用して並列セクションを指定しますpragma omp(上記の Cython の OpenMP サポートと非常によく似ています)。

プラグマ omp

PyPy

JIT Python コンパイラ PyPy は、マルチプロセッシング モジュール (以下を参照) をサポートし、PyPy-STM と呼ばれるプロジェクトを持っています。「PyPyの特別な開発中バージョンであり、同じプロセスで複数の独立した CPU を大量に消費するスレッドを並行して実行できます」。

補足: マルチプロセッシング

OpenMP は、複数のコアへの低レベル インターフェイスです。multiprocessing.モジュールはより高いレベルで動作し、Python データ構造を共有しますmultiprocessingが、OpenMP は C にコンパイルすると、C プリミティブ オブジェクト (整数や浮動小数点数など) で動作します。OpenMP を使用するのは、 'コードをコンパイルしています。コンパイルしていない場合 (たとえば、効率的なnumpyコードを使用していて、多くのコアで実行したい場合)、そのままにしておくmultiprocessingのがおそらく正しいアプローチです。

于 2016-04-20T11:17:47.170 に答える
35

GIL のため、CPython で CPU を集中的に使用するタスクにスレッドを使用する意味はありません。マルチプロセッシング ( example )が必要になるか、計算中に GIL を解放する C 拡張機能を使用する必要があります

たとえば、Cython で複数のスレッドを使用する C 拡張機能を簡単に作成できます。

于 2012-07-06T20:20:13.523 に答える
17

私の知る限りでは、Python 用の OpenMP パッケージはありません (もしあればどうなるかわかりません)。スレッドを直接制御したい場合は、スレッド化ライブラリの 1 つを使用する必要があります。ただし、他の人が指摘したように、GIL (グローバル インタープリター ロック) は、パフォーマンスのために Python でマルチスレッド化を行います...まあ、無意味です*。GIL は、一度に 1 つのスレッドのみがインタープリターにアクセスできることを意味します。

代わりに NumPy/SciPy を見ることをお勧めします。NumPy を使用すると、単一の操作で配列と行列を操作する Matlab 風のコードを記述できます。SciPy Wikiを参照してください。

探し始める他の場所:

* わかりました、無意味ではありませんが、時間が Python コードの外部で消費されない限り (経由で呼び出された外部プロセスpopenなどによって)、スレッドは利便性以外に何も購入しません。

于 2012-07-06T20:46:17.433 に答える
12

GIL をリリースして OpenMP を使用したい場合は、Cython を参照してください。いくつかの一般的なタスクに対して単純な並列処理を提供します。詳細については、Cythonのドキュメントを参照してください。

于 2012-10-25T23:35:54.637 に答える
9

たぶん、あなたの応答は Cython にあります:

「Cython は、cython.parallel モジュールを通じてネイティブの並列処理をサポートしています。この種の並列処理を使用するには、GIL をリリースする必要があります (GIL のリリースを参照してください)。現​​在、OpenMP をサポートしていますが、今後、より多くのバックエンドがサポートされる可能性があります。」 Cython ドキュメンテーション

于 2013-01-05T02:29:43.013 に答える
7

pympというパッケージがあり、著者はそれを OpenMP のような機能を Python にもたらすパッケージと説明しています。私はそれを使用してみましたが、ユースケースが異なります: ファイル処理です。出来た。使い方は至ってシンプルだと思います。以下は、GitHub ページからのサンプルです。

import pymp
ex_array = pymp.shared.array((100,), dtype='uint8')
with pymp.Parallel(4) as p:
    for index in p.range(0, 100):
        ex_array[index] = 1
        # The parallel print function takes care of asynchronous output.
        p.print('Yay! {} done!'.format(index))
于 2018-01-31T15:24:31.427 に答える