问题描述
我正在编写一个涉及 f = std::bind(std::bind(std::bind(...)))
使用的模板函数。
但我不确定 c++ 编译器是否足够智能以展开调用链。
我的意思是:
举个简单的例子:f2()
的运行速度是否比 f1()
稍快?
#include <functional>
int add(int a,int b) {
return a + b;
}
int main() {
using namespace std::placeholders;
auto f1 = std::bind(std::bind(&add,1,_1),2);
auto f2 = std::bind(&add,2);
return 0;
}
更新:
我做了一些实验。看来 f2()
确实比 f1()
运行得更快。如果你使用 std::function
,它会更慢。这是实验代码(ubuntu/gcc 7.5.0,启用了优化。没有优化,f2
是最慢的。)。在我的电脑上,输出是:
f1: 16851813
f2: 17567904
f3: 30655284
#include <chrono>
#include <iostream>
#include <functional>
int add(int a,int b,int c) {
return a + b + c;
}
int main() {
using namespace std::placeholders;
auto f1 = std::bind(std::bind(&add,_1,_2),2,_1);
auto f2 = std::bind(&add,_1);
std::function<int(int)> f3 = std::bind(&add,_1);
const int N = 10000000;
volatile int x = 0;
{
auto begin = std::chrono::system_clock::Now();
for (int n = 0; n < N; n++) {
x = f1(x);
}
auto end = std::chrono::system_clock::Now();
auto d = end - begin;
std::cout << "f1: " << d.count() << std::endl;
}
x = 0;
{
auto begin = std::chrono::system_clock::Now();
for (int n = 0; n < N; n++) {
x = f2(x);
}
auto end = std::chrono::system_clock::Now();
auto d = end - begin;
std::cout << "f2: " << d.count() << std::endl;
}
x = 0;
{
auto begin = std::chrono::system_clock::Now();
for (int n = 0; n < N; n++) {
x = f3(x);
}
auto end = std::chrono::system_clock::Now();
auto d = end - begin;
std::cout << "f3: " << d.count() << std::endl;
}
return 0;
}
解决方法
鉴于 import sys
import os
base_dir = os.path.dirname(__file__) or '.'
# Insert the package_dir_a directory at the front of the path.
package_dir_a = os.path.join(base_dir,'package_dir_a')
sys.path.insert(0,package_dir_a)
import py_file
使用类型擦除,因此应该对 std::function
执行等效于虚拟调用的代码,operator()
的结果可以知道真实类型并使用静态调用(这更简单由编译器内联)。
嵌套的 bind
会执行额外的静态调用,但可能是内联的,因此可能会给出相同的代码。
Quickbench Demo 确认您的示例:
嵌套或非嵌套 bind
的时间相同,但 bind
慢。