4

次の目的で使用する Python 拡張機能を C で作成する必要があります。

  1. ファイルに対して CPU 集中型の初期化を実行します。
  2. 初期化されたデータに依存して結果を返す複数の関数呼び出しを行います。と
  3. 完了したらメモリを解放する

1 つの解決策は、Python で「ステート ホルダー」クラスを実装することです。C で初期化を呼び出すと、初期化されたデータが返され、Python 状態オブジェクトに格納されます。次に、ステップ (2) を実行する必要があるたびに、それを C 関数に渡します。しかし、これは Python 側と C 側の間で発生するすべてのデータ シャトル/インターフェースを考えると、非常に非効率的です。

できればC側の状態オブジェクトを使って状態を維持したい。Python 側からの初期化呼び出しは、初期化されたすべてのデータを返すのではなく、ID のみを返すため、後続の呼び出しで必要なときに C 状態オブジェクトを参照できます。

C側で状態を維持するにはどうすればよいですか?

4

2 に答える 2

4

まず、実際にいただいた質問にお答えします。

struct StatePython が関与していない場合と同様に、C でa を作成します。

これらをコピーしない場合 ( で渡すだけstruct State *)、(intptr_t)theStatePtrPython の ID を取得するだけで済みます。もちろん、Python オブジェクトの存続期間が C オブジェクトの存続期間を超えないように注意する必要がありますが、それは可能です。

何らかの理由で構造体をコピー/移動する必要がある場合、または状態の管理にさらに支援が必要な場合 (たとえば、Python ID を弱い参照として扱う場合)、適切なコレクション (ハッシュ テーブル、ツリー、配列など) を選択してください。次に、キーを ID として Python に渡します。

ただし、ここで間違った部分を最適化している可能性があると思います。オブジェクトを前後に渡すことは何もありません。それは単なるポインターのコピーです。refcounting は問題になる場合がありますが、問題になることはめったになく、通常、ライフサイクル管理から得られるメリットにはそれだけの価値があります。パフォーマンスを低下させる可能性のある部分は、一連の Python 整数を Cintなどに継続的に変換する C コードです。これが問題である場合は、C 状態で C 構造体を作成し、それを Python オブジェクトでラップするだけです。内部のすべてを Python に公開します。

最後に、ここで実際に最適化が必要ですか? CPU を集中的に使用する作業を行っている場合、実際の作業は Python オブジェクト アクセスのコストを完全に覆い隠しているため、後者はプロファイリングにも表示されないに違いありません。まだプロファイリングを行っていない場合は、これが絶対に最初に行うべきことです。ここでの正しい答えは「何もしないでください」である可能性が高いからです。

それをさらに一歩進めてください。最適化のためにCコードをCでしか書いていないのなら、本当にそれが必要ですか? C でメモリ管理を処理するのは面倒でエラーが発生しやすく、Python の C 拡張モジュールで処理するのはさらに面倒です。どのように機能するかをまだ知らないときに初めて行うことは、支出のほぼ保証されたレシピです。実際のコードを書くのではなく、セグメンテーション違反やリークを追跡することにずっと時間を費やしています。したがって、次のことを順番に試して、それぞれをプロファイリングし、遅すぎる場合にのみリストを下に移動します。

  • アルゴリズムを Python で記述し、既存の CPython インタープリターを使用するだけです。
  • 最適なアルゴリズムがあることを確認してください。
  • CPython の代わりに PyPy を試してください。
  • Cythonを入手して、できるだけ変更を加えずに Python コードをコンパイルしてみてください。
  • コードを変更して、必要に応じて、静的型、C 関数の直接呼び出しなどの Cython 機能を利用します。
  • 下位レベルのコードは C で記述し、中間レベルのコード (状態オブジェクトを追跡して Python にラッパーを提示するもの) は Cython または Python でctypes.
  • お気に入りのインターフェイス メカニズムを使用して、下位レベルと中間レベル全体を C で記述します。多くの経験があり、非常に単純なことをしていない限り、これはおそらくネイティブ C API ではありませ
于 2012-11-07T22:36:34.317 に答える
0

Python から C への簡単なブリッジングについては、Cythonを確認してください。そこにあるドキュメントにはたくさんの例があります - ある種の状態オブジェクトを構築する方法を説明し、メモリの問題を説明するページにリンクしました。

これは cython/pyrex で書かれたAIO バインディング(github) の例で、かなり手の込んだ I/O の例です。私の経験では、このような I/O ルーチンを使用して圧縮形式でディスクにマーシャリングするカスタム オブジェクトをロールしました。メモリ内では、cython コードが python に表示されるものを処理します (カスタム ロールソケット オブジェクトなど) 。

私の最善のアドバイスは、.pyx例を検索することです。そうすれば、解決策を刺激するものを見つけることができます。

他のポスターにも同意します。拡張タイプがシステム全体に複雑さを追加するため、C への移行が必要かどうかを自問してください。

于 2012-11-07T23:06:20.097 に答える