8

Python を fortran90 に埋め込んで既存の fortran90 コードに Python 機能を追加するオプションを検討していました。numpy の f2py を使用して fortran90 で python を拡張することにより、逆の方法で実行できることを私は知っています。しかし、私は非常に最適化されたメイン ループを fortran に保持し、python を追加して追加のタスクを実行したり、fortran で実行する前にさらなる開発を評価したり、コードのメンテナンスを容易にしたりしたいと考えています。次の質問に対する回答を探しています。

1) python を fortran に埋め込むことができる既存のライブラリはありますか? (私は f2py を知っていますが、それは逆です) 2) Fortran から Python へのデータ転送、およびその逆のデータ転送をどのように処理しますか? 3) コールバック機能を実装するにはどうすればよいですか? (シナリオを少し説明させてください....私は Python で Func1_Python モジュールを呼び出す私の main_fortran プログラムを Fortran で持っています。今、この Func1_Python から、別の関数を呼び出したいです... fortran で Func2_Fortran と言ってください) 4)パフォーマンスの観点から、Pythonのインタープリターをfortran内に埋め込むことの影響です....ロード時間、実行時間、データ(倍精度の大きな配列)の送信など.

ご協力ありがとうございました!!

編集 1: 私が行っている作業に関する情報を追加して、議論の方向性を正しく設定したいと考えています。私は科学計算に興味があります。そのため、倍精度で巨大な配列/行列に多くの作業を行い、浮動小数点演算を行っていました。したがって、実際に作業を行うための fortran 以外のオプションはほとんどありません。Python をコードに含めたい理由は、必要に応じていくつかの基本的な計算を行うために NumPy を使用し、最小限の労力でコードの機能を拡張できるためです。たとえば、Python と他のパッケージ (PyFoam ライブラリを使用した OpenFoam など) をリンクするために利用可能ないくつかのライブラリを使用できます。

4

7 に答える 7

8

1. やらない

Fortran 拡張機能を備えた Python プログラムを使用する代わりに、Fortan プログラム内に Python コードを追加したいと考えていることは承知しています。私の最初のアドバイスは、これをしないことです。Fortran は配列演算で Python よりも高速ですが、Python は Fortran よりも書きやすく、OOP 手法を使用して Python コードを拡張しやすく、Python は重要なライブラリにアクセスできる場合があります。あなたは、Fortran で超最適化されたメイン ループを持つことに言及しています。Fortran は、超最適化された内部ループに最適です。Numpy を使用して Python プログラムで Fortran 配列を渡すロジックは、Fortran で Python オブジェクトを正しく処理するために必要なロジックよりもはるかに簡単です。

科学計算プロジェクトをゼロから始めるときは、常に最初に Python で記述し、パフォーマンスのボトルネックを特定して、それを Fortran に変換します。検証済みの Python コードに対してより高速な Fortran コードをテストできるため、コードが正しく機能していることを簡単に示すことができます。

既存のコードがあるため、Fortran で作成されたモジュールで Python コードを拡張するにはリファクタリングが必要ですが、このプロセスは簡単です。初期化コードをメイン ループから分離し、ループを論理的な断片に分割し、これらのルーチンをそれぞれ Python 関数でラップします。次に、メインの Python コードで Fortran サブルーチンを呼び出し、必要に応じてこれらを Python 関数とインターリーブできます。このプロセスでは、Fortran のメイン ループにある多くの最適化を保持できる場合があります。F2PY はこのためのかなり標準的なツールであるため、どのような問題が発生しても助けてくれる人を見つけるのは難しくありません。

2. システムコール

SYSTEMPython コードを呼び出す Fortran コードが絶対に必要な場合は、その逆ではなく、Fortran コードでデータをディスクに書き込み、Python コードをまたはで実行するのが最も簡単な方法ですEXECUTE_COMMAND_LINE。使用する場合EXECUTE_COMMAND_LINE、Python コードでその結果を stdout に出力し、Fortran コードでそれを文字データとして読み取ることができます。大量の出力 (たとえば、大きな行列) がある場合は、Fortran コードが読み取るファイルを Python コードで出力する方が理にかなっています。ディスクの読み取り/書き込みのオーバーヘッドは、このために法外に大きくなる可能性があります。また、データを出力する Fortran コード、データを読み取る Python コード、再出力する Python コード、データを再入力する Fortran コードを記述する必要があります。このコードは簡単に記述してテストできるはずですが、コードを編集する際にこれら 4 つの部分を同期させておくと、頭痛の種になる可能性があります。

(このアプローチは、このスタック オーバーフローの質問で試行されます)

3. Fortran の C に Python を埋め込む

私が知る限り、メモリ内の Python オブジェクトを Fortran に直接渡す方法はありません。ただし、Fortran コードは C コードを呼び出すことができ、C コードには Python を埋め込むことができます。(拡張と埋め込みに関する Python チュートリアルを参照してください。) 一般に、Python を拡張する (ポイント 1 で推奨するように) ほうが、C/C++ に埋め込むよりも望ましいです。PythonとFortran間の通信の問題は、Python と C の間、または C と Fortran の間で発生する可能性があるためです。Python を Fortran の C に実際に埋め込んでいる人がいるかどうかはわかりません。そのため、助けを求めるのは難しいでしょう。

于 2013-06-13T19:00:15.823 に答える
4

この問題を解決するためにいくつかのアプローチを試しましたが、おそらく最適な方法を 1 つ見つけました。アプローチと結果を簡単にリストアップします。

1) システム コールによる埋め込み: Fortran から Python にアクセスするたびに、システム コールを使用して Python スクリプトを実行し、それらの間でデータを交換します。このアプローチの速度は、ディスクの読み取り、書き込みによって制限されます (キャッシュ レベルでコードを最適化するこの時代では、ディスクにアクセスすることは大罪です)。また、スクリプトを実行するたびにインタープリターを初期化する必要があり、これはかなりのオーバーヘッドです。300 タイムステップで実行される単純なルンゲ クッタ 4 次メソッドの実行には、なんと 59 秒かかりました。

2) C 経由で Fortran から Python に移行: ISO_C バインディングを使用して、Fortran と C の間で通信します。Python インタープリターを C 内に組み込みます。部分的に動作するようになりましたが、しばらくして、より良い方法を見つけたので、このアイデアを破棄しました。ただし、完全を期すためにこれを評価したいと思います。

3) f2py を使用して Fortran サブルーチンを Python にインポートする (拡張) : ここでは、メイン ループを Fortran から取り出し、Python でコーディングします (このアプローチは、Fortran による Python の拡張と呼ばれます)。f2py ( http://cens.ioc.ee/projects/f2py2e/usersguide/ ) を使用して、すべての Fortran サブルーチンを Python にインポートします。科学アプリケーション、つまり Python の最も外側のループ (通常は時間ループ) で最も重要なデータを保持できる柔軟性があるため、他のアプリケーションと結合できます。しかし、Fortran と Python の間で必要以上のデータを交換しなければならないという欠点もあります。同じルンゲ クッタの 4 次メソッドの例では、実行に 0.372 秒かかりました。

4) 拡張による埋め込みの模倣: これまで、埋め込み (メイン ループは fortran のままで、必要に応じて python を呼び出します) と拡張 (メイン ループは python のままで、必要に応じて fortran を呼び出します) の 2 つの純粋なアプローチを見てきました。それを行う別の方法がありますが、それが最も最適であることがわかりました。メイン ループの一部を Python に転送するとオーバーヘッドが発生しますが、これは常に必要であるとは限りません。このオーバーヘッドを取り除くために、変更なしでサブルーチンに変換される Fortran のメイン ループを維持し、Fortran のメイン ループを呼び出すだけの疑似メイン ループを Python に用意し、プログラムをあたかもそれが私たちのものであるかのように実行することができます。手付かずの Fortran プログラム。必要に応じて、コールバック関数を使用して、必要なデータで Python に戻り、スクリプトを実行して、再び fortran に戻ることができます。このアプローチでは、ルンゲ クッタ 4 次法では 0.083 秒かかりました。コードのプロファイリングを行ったところ、Python インタープリターの初期化と読み込みに 0.075 秒かかり、プログラムは 0.008 秒しかかからなかったことがわかりました (これには、Python への 300 のコールバック関数が含まれています)。元の fortran コードは 0.007 秒かかりました。したがって、このアプローチを使用すると、Python のような柔軟性を備えたほぼ Fortran のようなパフォーマンスが得られます。

于 2013-06-21T10:08:11.143 に答える
4

を使用してこれを行う非常に簡単な方法がありますf2py。Python メソッドを作成し、Fortran サブルーチンへの入力として追加します。cf2pyフックと型宣言の両方で、EXTERNAL戻り値の型として宣言しREAL*8ます。Fortran コードには、python メソッドが保存されているアドレスへのポインターが含まれます。糖蜜のように遅くなりますが、アルゴリズムのテストには役立ちます。私はこれを頻繁に行います (私は多くの古代のスパゲッティ Fortran を Python モジュールに移植しています...) また、従来の Fortran で最適化された Scipy 呼び出しなどを使用する優れた方法でもあります

于 2014-05-18T19:21:42.767 に答える