4

大きな Swig Python モジュールがあります。C++ ラッパーは、最終的に約 320,000 LoC になります (私が推測するヘッダーを含む)。私は現在、これを -O1 でコンパイルしています。g++ は、サイズが 44MiB のバイナリを生成し、コンパイルに約 3 分かかります。

最適化をオフにすると (-O0)、バイナリは 40MiB で出力され、コンパイルに 44 秒かかります。

-O0 を指定してラッパーをコンパイルすると、Python モジュールのパフォーマンスが大幅に低下しますか? さまざまな最適化レベルでモジュールのパフォーマンスをプロファイリングする前に、この種の分析を以前に行ったことがありますか、それが重要かどうかについて洞察を持っていますか?

4

2 に答える 2

3

-O0 は、gcc によって実行されるすべての最適化を無効にします。そして最適化が重要です。

そのため、アプリケーションについて十分な知識がないと、アプリケーションのパフォーマンスが低下する可能性があります。

通常、安全に使用できる最適化レベルは -O2 です。

GCC によって実行される最適化の種類は、http: //gcc.gnu.org/onlinedocs/gcc/Optimize-Options.htmlで確認できます。

しかし最後に、正確に知りたい場合は、さまざまなレベルとプロファイルでコンパイルする必要があります。

于 2012-12-09T20:49:51.463 に答える
2

これは、SWIGモジュールに関係なく悪いことです。あなたがそれらが起こるのを防ぐならばあなたが逃すであろうとしても起こる多くの最適化があります。gcc -O1

選択したコンパイラによって生成されたasmを調べることで、違いを確認できます。これらのうち、私が自明に知っているものは、SWIGの生成されたラッパーに有害です。

  1. デッドコードの除去:

    void foo() {
      int a = 1;
      a = 0;
    }
    

    -O1を使用すると、この完全に無意味なコードが完全に削除されます。

    foo:
            pushl   %ebp
            movl    %esp, %ebp
            popl    %ebp
            ret
    

    一方、-O0を使用すると、次のようになります。

    foo:
            pushl   %ebp
            movl    %esp, %ebp
            subl    $16, %esp
            movl    $1, -4(%ebp)
            movl    $0, -4(%ebp)
            leave
            ret
    
  2. レジスタ割り当ては、ローカル変数が多数ある関数で悪影響を受けます。ほとんどのSWIGラッパー関数はこれによる影響を受けます。しかし、これの簡潔な例を示すのは難しいです。

  3. 別の例として、プロトタイプのSWIGラッパーをコンパイルするgccからの出力:

    int foo(unsigned int a, unsigned int b, unsigned int c,  unsigned int d);
    

    で生成-O0

    Java_testJNI_foo:
            pushl   %ebp
            movl    %esp, %ebp
            subl    $88, %esp
            movl    16(%ebp), %eax
            movl    %eax, -48(%ebp)
            movl    20(%ebp), %eax
            movl    %eax, -44(%ebp)
            movl    24(%ebp), %eax
            movl    %eax, -56(%ebp)
            movl    28(%ebp), %eax
            movl    %eax, -52(%ebp)
            movl    32(%ebp), %eax
            movl    %eax, -64(%ebp)
            movl    36(%ebp), %eax
            movl    %eax, -60(%ebp)
            movl    40(%ebp), %eax
            movl    %eax, -72(%ebp)
            movl    44(%ebp), %eax
            movl    %eax, -68(%ebp)
            movl    $0, -32(%ebp)
            movl    -48(%ebp), %eax
            movl    %eax, -28(%ebp)
            movl    -56(%ebp), %eax
            movl    %eax, -24(%ebp)
            movl    -64(%ebp), %eax
            movl    %eax, -20(%ebp)
            movl    -72(%ebp), %eax
            movl    %eax, -16(%ebp)
            movl    -16(%ebp), %eax
            movl    %eax, 12(%esp)
            movl    -20(%ebp), %eax
            movl    %eax, 8(%esp)
            movl    -24(%ebp), %eax
            movl    %eax, 4(%esp)
            movl    -28(%ebp), %eax
            movl    %eax, (%esp)
            call    foo
            movl    %eax, -12(%ebp)
            movl    -12(%ebp), %eax
            movl    %eax, -32(%ebp)
            movl    -32(%ebp), %eax
            leave
            ret
    

    -O1ちょうど生成するものと比較して:

    Java_testJNI_foo:
            pushl   %ebp
            movl    %esp, %ebp
            subl    $24, %esp
            movl    40(%ebp), %eax
            movl    %eax, 12(%esp)
            movl    32(%ebp), %eax
            movl    %eax, 8(%esp)
            movl    24(%ebp), %eax
            movl    %eax, 4(%esp)
            movl    16(%ebp), %eax
            movl    %eax, (%esp)
            call    foo
            leave
            ret
    
  4. g ++を使用すると-O1、次の場合にはるかにスマートなコードを生成できます。

    %module test
    
    %{
    int value() { return 100; }
    %}
    
    %feature("compactdefaultargs") foo;
    
    %inline %{
      int foo(int a=value(), int b=value(), int c=value()) {
        return 0;
      }
    %}
    

簡単に言うと、最適化を完全に無効にすると、GCCは非常に単純なコードを生成します。これは、自動生成されたコードのスタイルが与えられていない限り、他のプログラムと同様にSWIGラッパーにも当てはまります。

于 2012-12-10T20:57:45.710 に答える