C ++优化级别是否会影响Swig Python模块的性能

时间:2012-12-09 20:40:01

标签: c++ python optimization g++ swig

我有一个很大的Swig Python模块。 C ++包装器最终约为320,000 LoC(包括我猜的头文件)。我目前用-O1编译它,g ++生成一个大小为44MiB的二进制文件,编译它需要大约3分钟。

如果我关闭优化(-O0),二进制文件将以40MiB出现,编译需要44秒。

使用-O0编译包装器会显着损害python模块的性能吗?在我开始分析不同优化级别的模块性能之前,有没有人在此之前进行过这种分析,或者对是否重要有任何了解?

2 个答案:

答案 0 :(得分:3)

-O0取消激活gcc执行的所有优化。优化很重要。

因此,如果您的应用程序中没有很多知识,我可能会建议这会损害您的应用程序的性能。

通常安全的优化级别是-O2。

您可以在以下位置检查GCC执行的优化类型: http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html

但最后,如果你想确切地知道你应该在不同的级别和个人资料中进行编译。

答案 1 :(得分: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. 另一个例子,gcc的输出为原型编译SWIG包装器:

    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. 使用-O1 g ++可以生成更智能的代码:

    %module test
    
    %{
    int value() { return 100; }
    %}
    
    %feature("compactdefaultargs") foo;
    
    %inline %{
      int foo(int a=value(), int b=value(), int c=value()) {
        return 0;
      }
    %}
    
  5. 简短的回答是完全禁用优化GCC会生成极其天真的代码 - 对于SWIG包装器而言,这与任何其他程序一样,如果没有给出自动生成代码的样式,那么。