29

CPUを集中的に使用する文字列操作を行うコードがあり、パフォーマンスを向上させる方法を探していました。

(編集:私は、最長の共通部分文字列を見つける、cでステートマシンとしてより適切に表現される可能性のある正規表現を多数実行する、HTMLからコメントを削除する、などの作業を行っています。)

私は現在、 Cythonについて多くの良いことを聞いた後、コードの一部をCythonに移植することを検討しています。ただし、Cythonの主な焦点は数値計算であり、文字列の操作はほとんど文書化されていないようです。

Unicodeも大きな問題になる可能性があります。

私の質問は次のとおりです。

  1. 文字列のことでCythonを気にする必要がありますか?誰かがcythonでのこのタイプの処理の経験があり、共有できますか?
  2. Cythonのドキュメントに何か足りないものがありますか?Cythonでの文字列の操作に関するチュートリアル/リファレンス/ドキュメントを知っている人はいますか?
4

6 に答える 6

12

「プロファイルする」という回答に投票しましたが、これを追加したかったのです。可能な場合、実行できる最適な最適化は、Python 標準ライブラリまたは組み込み関数を使用して、必要なタスクを実行することです。これらは通常 C で実装され、Cython で記述された拡張機能を含む、あらゆる拡張機能とほぼ同等のパフォーマンスを提供します。アルゴリズムが Python で文字単位のループを実行している場合、可能であれば、それらを最初に実行する必要があります。

しかし、ビルトインや他の既存の標準ライブラリに関して再加工できないアルゴリズムがある場合、Cython は合理的なアプローチのように思えます。疑似 Python をネイティブ コードにコンパイルするだけで、他の操作と同様に文字列操作に適しています。しかし、慣用的な Python コードを手渡すだけで、Cython を使用することで大きなメリットが得られるとは思えません。各アルゴリズムの一部またはすべてを C で書き直すことができれば、最大のメリットが得られます。これにより、低レベルの操作が Python/C の壁を越えて変数を常に変換することはなくなります。

最後に、Unicode - あなたはそれが「大きな問題」である可能性があることをほのめかしましたが、それをどのように使用しているかは特定していません。Cython はおそらく、Unicode を処理する関連する Python API を呼び出す C コードを生成するため、機能が制限されることはほとんどありません。ただし、C で Unicode 文字列を処理することは自明ではなく、C でアルゴリズムの一部を書き直してパフォーマンスを向上させるという考えは、努力する価値がないことを意味する場合があります。多くの古典的な文字列アルゴリズムは、多くの Unicode エンコーディングでは単純に機能しません。これは、文字ごとに 1 ユニットのストレージを持つという従来の意味での「文字列」ではありません。

于 2009-06-03T12:41:38.797 に答える
9

完全を期すために、私が最終的に行ったことは、文字列操作コード (の一部) を C で記述しただけです。

結局のところ、 C 拡張機能を Python に書き始めるのはとてつもなく簡単です。Unicode 文字列は Py_UNICODE の単なる配列であり、Python ビルドに応じて int または short になります。

次のようなコードを変換すると、x20 の改善が得られました

s = re.sub(r' +', ' ', s)

cに。より複雑な正規表現でも同様の改善が得られましたが、c コードはすぐに非常に複雑になります。

全体として、書き直し後、スループットが 20% 向上しました。私は今、書き直すものをもっと探しています...

于 2009-11-26T11:36:11.560 に答える
8

「ばかばかしいほど簡単」は、非常に相対的な用語です。「はじめる」とはまさにこのこと。C で堅牢な拡張機能を作成するには、参照カウント、メモリの割り当て/解放、エラー処理などに細心の注意を払う必要があります。Cython がその多くを行います。

Cython の非 Unicode 文字列は、Python の str オブジェクトか、C のように char の配列です。どの Cython 固有のドキュメントが必要だと思いますか?

Cython を試してみることをお勧めします。しかし、それを行う前に、非効率な Python コードを調べることを強くお勧めします。途方もなく簡単に大幅なスピードアップを実現できる場合があります。

たとえば、一連の空白文字を圧縮する ... を使用して

re.sub(' +', ' ', s) # one space in pattern

実行の長さが 1 である、おそらく珍しくないケースでは、スペースがスペースに置き換えられることを意味します。すべての実行の長さが 1 の場合、入力文字列の参照カウントを簡単にインクリメント (またはデクリメントしないなど) し、それを返すことができる場合、新しい置換文字列が作成されます。

re.sub('  +', ' ', s) # two spaces in pattern

まったく同じ結果が得られ、より高速に実行される可能性があります...見てみましょう:

すべての実行の長さ 1: 3.4 倍の速度で実行されます。表示されていません: 入力文字列が長いほど、より良い結果が得られます。

\python26\python -mtimeit -s"s='now is the winter of our discontent'; import re; x = re.compile(' +').sub" "x(' ', s)"
100000 loops, best of 3: 8.26 usec per loop

\python26\python -mtimeit -s"s='now is the winter of our discontent'; import re; x = re.compile('  +').sub" "x(' ', s)"
100000 loops, best of 3: 2.41 usec per loop

長さ 2 の 1 つのランで、速度比は 2.5 です。すべての実行の長さが 2 の場合、速度比は 1.2 です。すべてを考慮すると、キーストローク 1 回の投資に対する見返りは悪くありません。

于 2009-11-26T23:57:05.400 に答える
6

私は最近 Cython を紹介され、重要なプロジェクトで使用するために大規模な C および C++ ライブラリをラップすることに大きな成功を収めました。生成された Python 拡張機能の一部は、実際には既に運用環境で実行されています。まず、Cython は間違いなく良い選択です。

そうは言っても、本当にすべてのコードを Cython で記述したいのか、それとも C/C++ コードを記述して単に Cython からそれらの関数にアクセスできるようにしたいのかを検討する必要があります。明らかに、これは C および/または C++ の快適さのレベルに部分的に依存します。

std::string文字列を扱っているので、 .NET ではなく from C++を使用することで、おそらく生活をよりシンプルにすることができますchar*。非常に簡単に cython にインポートできfrom libcpp.string cimport string、標準の cython を介して文字列型で変数を宣言できます。cdef string ...

于 2012-02-17T20:37:35.280 に答える
5

これは非常に興味深い問題です。Cython の中核は、Python を C データ型と統合するためのツールです。おそらく、特定の Numpy 機能ほど需要がないため、文字列の処理を支援する機能は提供されません。

そうは言っても、Cython を使用して、記述したタイプの問題を処理するように設計された既存の C/C++ ライブラリと連携させることができます。HTML/XML を処理するには、たとえばlibxmlを調べたいと思うかもしれません。ただし、(もちろん)そのための既製の Python バインディングが既に用意されています。私は HTML を処理するために lxml を広範囲に使用してきましたが、必要なことはすべて実行でき、高速に実行できます。さらに、Unicode をうまく処理できます。

あなたの場合、lxml とカスタムメイドの C 関数の組み合わせが最適だと思います。たとえば、バイトレベルで実行できるように、C で最も長い部分文字列を見つけるための高速関数を「簡単に」作成できます (C の文字列は、バイトの配列である単なる char* であることを思い出してください)。次に、それらを python (Cython を使用すると非常に簡単になります) にマップして戻すことができ、Unicode 抽象化された天国で続行できます :)。確かに些細なことではありませんが、アプリのパフォーマンスがそれに依存している場合は、努力する価値があるかもしれません.

もちろん、C/C++ で Unicode を操作するための優れた (自明ではありませんが) アプローチもあります。Evan Jones によるこの記事は、努力する価値があるかどうかを判断するのに役立つかもしれません。

于 2009-10-13T15:02:17.597 に答える
4

Cython は実際には CPython の Py_UNICODE タイプをサポートしているため、たとえば、Unicode 文字列を直接反復処理したり、文字を C の速度で比較したりできます。見る

http://docs.cython.org/src/tutorial/strings.html

于 2011-04-16T14:15:20.443 に答える