c++ - boost::mp11::mp_with_index 与 std::function 数组的性能比较

标签 c++ boost callback benchmarking std-function

考虑以下两个片段:

// Option (1).
boost::mp11::mp_with_index<N>(i,
                              [&](const auto i){ function<i>(/* args... */); });

// Option (2).
inline static const std::array<std::function<void(/* Args... */)>, N>
    functionArray{function<0>, ..., function<N-1>};
functionArray[i](/* args... */);

哪里N是大约在 [0, 20], i 范围内的编译时间大小是 0 之间的运行时索引和N-1 ,和template <size_t I> function(/* Args... */)是具有已知签名的模板函数。 这两个选项中哪一个最快?

注意:我知道boost::mp11::mp_with_index基本上创建了一个 switch 语句,允许将运行时索引转换为编译时索引。这引入了一些间接性,但我预计这不会太昂贵。同样,我知道std::function由于类型删除引入了一些间接性。我的问题是:两种间接类型中哪一种最有效?

最佳答案

std::array<std::function<void(Args...)>, N>与纯指针数组相比,可能会引入一些开销 std::array<void(*)(Args...), N> .

查看生成的程序集 https://godbolt.org/z/a8z9aKs7P ,可以得出以下结论:

boost::mp11::mp_with_index被编译为一个分支表,其中包含 N 个不同指令的 N 个地址,这些指令只需调用 function<I>当跳到。因此,它会在分支表中查找地址,跳转到该地址,然后再次跳转到所需的函数。

这个分支表可以通过简单地存储 function<I> 的地址来简化。 ,只需要一跳。当您有一个函数指针数组时,就会发生这种情况,该数组本质上是一个分支表。

std::function类似,但调用 std::function比调用常规函数指针稍微复杂一些。


注意 clang 在 -O2 的优化方面很糟糕甚至-O3boost::mp11::mp_with_index<N>实际上是一堆 if/else 语句,应该很容易编译,就像 switch 一样。 ,但 clang 未能做到这一点(并留下 N “比较和条件跳转”指令)。函数指针数组是这里唯一好的选择。

关于c++ - boost::mp11::mp_with_index 与 std::function 数组的性能比较,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70494728/

相关文章:

c++ - 在 C++ 中使用 "this"构造函数?

c++ - 如何使用目录中的所有文件夹填充 C++ 中的列表框

c++ - 从 Boost.Spirit.Qi 制作shared_ptr

c++ - 如何使用类似 boost.parameter 的语法获得更快的编译速度?

c++ - 将临时值存储为某种数据类型时,算术运算的标准规则是什么?

c++ - boost::copy_graph 的vertex_copy 是如何工作的?

c++ - Boost 错误代码引用

C 系统调用处理程序引用具有不同返回类型和参数数量的函数

javascript - 如何打破 async.js 每个循环?

javascript - Date.getTime 没有在回调中前进