Performance 类别';s运算符()或将函数绑定为函子?

Performance 类别';s运算符()或将函数绑定为函子?,performance,c++11,coding-style,functor,Performance,C++11,Coding Style,Functor,有两种方法可以生成函子(保存状态的函数): 绑定函数并定义状态:bind(f,_1,state) 双g(双x,双状态){ 返回x+状态; } 函数f=bind(g,_1,state) 使用()运算符和类: 我发现bind-方法的编写速度更快,但我想知道是否有一些隐藏的石头,因为在大多数文献中,我将functor视为类的()操作符。我认为bind是从函数式语言(正如标题文件名告诉您的)中得到启发的。 我认为它相当等效,因为它是一个模板函数,但可能通过内置调用进行优化 这是我第一次看到这个函数,所以

有两种方法可以生成函子(保存状态的函数):

  • 绑定函数并定义状态:
    bind(f,_1,state)

    双g(双x,双状态){ 返回x+状态; } 函数f=bind(g,_1,state)

  • 使用
    ()
    运算符和类:


  • 我发现
    bind
    -方法的编写速度更快,但我想知道是否有一些隐藏的石头,因为在大多数文献中,我将functor视为类的
    ()
    操作符。

    我认为
    bind
    是从函数式语言(正如标题文件名告诉您的)中得到启发的。 我认为它相当等效,因为它是一个模板函数,但可能通过内置调用进行优化

    这是我第一次看到这个函数,所以我需要查看asm以查看差异,然后我将重新发布;)

    尽管如此,它不允许您在functor中使用其他方法,因此许多用法仍然需要
    operator()

    [编辑] 好的,我看到asm:bind添加了很多代码,因为它的模板与“经典方式”相比。因此,我建议您使用strucs的方式来使用(即,只是一个函子)。此外,阅读这样的代码更容易理解。 如果你使用参数替换,绑定是好的,但为了简单使用,它是一个激光佳能来切割你的奶酪:P
    [/EDIT]

    3。way是一个lambda表达式:

    auto f = [state]( double x ) { return x * state; };
    

    看来
    struct
    是一种更快的方法:

    11:01:56 ~/try 
    > g++ -std=c++11 main.cpp ; ./a.out
    in 2265 ms, functor as a struct result = 1.5708e+16
    in 31855 ms, functor through bind result = 1.5708e+16
    11:02:33 ~/try 
    > clang++ -std=c++11 main.cpp ; ./a.out
    in 3484 ms, functor as a struct result = 1.5708e+16
    in 21081 ms, functor through bind result = 1.5708e+16
    
    守则:

    #include <iostream>
    #include <functional>
    #include <chrono>
    
    using namespace std;
    using namespace std::placeholders;
    using namespace std::chrono;
    
    struct fs {
      double s;
      fs(double state) : s(state) {}
      double operator()(double x) {
        return x*s;
      }
    };
    
    double fb(double x, double state) {
      return x*state;
    }
    
    int main(int argc, char const *argv[]) {
      double state=3.1415926;
    
      const auto stp1 = system_clock::now();
      fs fstruct(state);
      double sresult;
      for(double x=0.0; x< 1.0e8; ++x) {
        sresult += fstruct(x);
      }
      const auto stp2 = high_resolution_clock::now();
      const auto sd = duration_cast<milliseconds>(stp2 - stp1);  
      cout << "in " << sd.count() << " ms, "; 
      cout << "functor as a struct result = " << sresult << endl;
    
      const auto btp1 = system_clock::now();
      auto fbind = bind(fb, _1, state);
      double bresult;
      for(double x=0.0; x< 1.0e8; ++x) {
        bresult += fbind(x);
      }
      const auto btp2 = high_resolution_clock::now();
      const auto bd = duration_cast<milliseconds>(btp2 - btp1);  
      cout << "in " << bd.count() << " ms, "; 
      cout << "functor through bind result = " << bresult << endl;
    
      return 0;
    }
    
    在main.cpp中:

      const auto bstp1 = system_clock::now();
      auto fbindstruct = bind(fbs(), _1, state);
      double bsresult;
      for(double x=0.0; x< 1.0e8; ++x) {
        bsresult += fbindstruct(x);
      }
      const auto bstp2 = high_resolution_clock::now();
      const auto bsd = duration_cast<milliseconds>(bstp2 - bstp1);  
      cout << "in " << bsd.count() << " ms, "; 
      cout << "functor through bind-struct result = " << bsresult << endl;
    
    更新(2)

    在类似时间添加优化结果:

    > g++ -std=c++11 -O2 main.cpp ; ./a.out
    hi
    in 536 ms, functor as a struct result = 1.5708e+16
    in 510 ms, functor through bind result = 1.5708e+16
    in 472 ms, functor through bind-struct result = 1.5708e+16
    12:31:33 ~/try 
    > clang++ -std=c++11 -O2 main.cpp ; ./a.out
    hi
    in 388 ms, functor as a struct result = 1.5708e+16
    in 419 ms, functor through bind result = 1.5708e+16
    in 456 ms, functor through bind-struct result = 3.14159e+16
    
    GCC 4.8.1和Clang 3.3

    注意Clang 3.3为“bind struct”案例给出了错误的结果

    更新(3)


    std::bind(f,_1,state)
    中的
    f
    是什么?
    std::bind
    所做的基本上是创建一个类似于第二种情况的对象。所以在现实中,两者之间并没有太大的区别。第二种方法在书籍等中更为常见。因为
    std::bind
    和C++11仍然是很新的。@KennyTM我编辑了这个示例。因为这是用C+11标记的,还有另一种方法,lambda函数带有捕获。这是一个很好的快速解决方案,但我不知道如何在不同的函数中使用它。它似乎不是模块化的——您必须在函数的定义中定义状态。在另外2个模块中,您在单独的模块中定义函数,并在初始化时定义状态。您的基准测试并不重要,因为有许多情况:bind可以与数量可变的参数一起使用,为了详尽无遗,您需要根据参数的数量进行检查。但是,这并不是全部,有些用途不是函数。看,这只是一个开始的想法。从答案来看,我会使用bind,因为它可以更快地编写原型,然后如果需要进一步优化,我会测量其他选项。如果使用-O2优化,我会获得相同的速度。你看过asm有没有优化。谢谢你的关注
      const auto bstp1 = system_clock::now();
      auto fbindstruct = bind(fbs(), _1, state);
      double bsresult;
      for(double x=0.0; x< 1.0e8; ++x) {
        bsresult += fbindstruct(x);
      }
      const auto bstp2 = high_resolution_clock::now();
      const auto bsd = duration_cast<milliseconds>(bstp2 - bstp1);  
      cout << "in " << bsd.count() << " ms, "; 
      cout << "functor through bind-struct result = " << bsresult << endl;
    
    > g++ -std=c++11 main.cpp ; ./a.out
    hi
    in 2178 ms, functor as a struct result = 1.5708e+16
    in 31972 ms, functor through bind result = 1.5708e+16
    in 32083 ms, functor through bind-struct result = 1.5708e+16
    12:15:27 ~/try 
    > clang++ -std=c++11 main.cpp ; ./a.out
    hi
    in 3758 ms, functor as a struct result = 1.5708e+16
    in 23503 ms, functor through bind result = 1.5708e+16
    in 23508 ms, functor through bind-struct result = 1.5708e+16
    
    > g++ -std=c++11 -O2 main.cpp ; ./a.out
    hi
    in 536 ms, functor as a struct result = 1.5708e+16
    in 510 ms, functor through bind result = 1.5708e+16
    in 472 ms, functor through bind-struct result = 1.5708e+16
    12:31:33 ~/try 
    > clang++ -std=c++11 -O2 main.cpp ; ./a.out
    hi
    in 388 ms, functor as a struct result = 1.5708e+16
    in 419 ms, functor through bind result = 1.5708e+16
    in 456 ms, functor through bind-struct result = 3.14159e+16