C++ std::function & lambda 性能损失

pre

以下是基于上述问题做的测试,结果:

    1. std::function 相当于一次 virtual function 的调用成本
    1. 如果可能,auto arg / template 是接近原始调用的
    1. 否则:lambda 是一个更好的选择

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
static const unsigned N = 10;

struct loop3_lambda {
static void impl() {
double sum = 0.0;

const auto fn = [](double a, double b, double c) {
const auto subFn = [](double x, double y) { return x / (y + 1); };
return sin(a) + log(subFn(b, c));
};

for (unsigned i = 1; i <= N; ++i) {
for (unsigned j = 1; j <= N; ++j) {
for (unsigned k = 1; k <= N; ++k) {
sum += fn(i, j, k);
}
}
}
}
};

struct loop3_function {
static void impl() {
double sum = 0.0;

const std::function<double(double, double, double)> fn = [](double a, double b, double c) {
const auto subFn = [](double x, double y) { return x / (y + 1); };
return sin(a) + log(subFn(b, c));
};

for (unsigned i = 1; i <= N; ++i) {
for (unsigned j = 1; j <= N; ++j) {
for (unsigned k = 1; k <= N; ++k) {
sum += fn(i, j, k);
}
}
}
}
};

struct loop3_template {
template <class func_tt, class... args_tt> static void impl(func_tt&& func, args_tt&& ... args) {
double sum = 0.0;

for (unsigned i = 1; i <= N; ++i) {
for (unsigned j = 1; j <= N; ++j) {
for (unsigned k = 1; k <= N; ++k) {
sum += func(i, j, k);
}
}
}
}
};

struct loop3_function_arg {
static void impl(std::function<double(double, double, double)>&& func) {
double sum = 0.0;

for (unsigned i = 1; i <= N; ++i) {
for (unsigned j = 1; j <= N; ++j) {
for (unsigned k = 1; k <= N; ++k) {
sum += func(i, j, k);
}
}
}
}
};

struct loop3_function_2_lambda {
static void impl(std::function<double(double, double, double)> &&func) {
double sum = 0.0;

const auto lambda_call = [func](double a, double b, double c) {
return func(a, b, c);
};

for (unsigned i = 1; i <= N; ++i) {
for (unsigned j = 1; j <= N; ++j) {
for (unsigned k = 1; k <= N; ++k) {
sum += lambda_call(i, j, k);
}
}
}
}
};

struct loop3_auto {
static void impl(auto &&func) {
double sum = 0.0;

for (unsigned i = 1; i <= N; ++i) {
for (unsigned j = 1; j <= N; ++j) {
for (unsigned k = 1; k <= N; ++k) {
sum += func(i, j, k);
}
}
}
}
};

struct loop3_raw {
static void impl() {
double sum = 0.0;
for (unsigned i = 1; i <= N; ++i) {
for (unsigned j = 1; j <= N; ++j) {
for (unsigned k = 1; k <= N; ++k) {
sum += sin((double)i) + log((double)j / (k + 1));
}
}
}
}
};

static void loop3_lambda_test(benchmark::State &state) {
for (auto _ : state) {
loop3_lambda::impl();
}
}

static void loop3_function_test(benchmark::State &state) {
for (auto _ : state) {
loop3_function::impl();
}
}

static void loop3_template_test(benchmark::State &state) {
for (auto _ : state) {
loop3_template::impl([](double a, double b, double c) {
const auto subFn = [](double x, double y) { return x / (y + 1); };
return sin(a) + log(subFn(b, c));
});
}
}

static void loop3_function_arg_test(benchmark::State &state) {
for (auto _ : state) {
loop3_function_arg::impl([](double a, double b, double c) {
const auto subFn = [](double x, double y) { return x / (y + 1); };
return sin(a) + log(subFn(b, c));
});
}
}

static void loop3_function_2_lambda_test(benchmark::State &state) {
for (auto _ : state) {
loop3_function_2_lambda::impl([](double a, double b, double c) {
const auto subFn = [](double x, double y) { return x / (y + 1); };
return sin(a) + log(subFn(b, c));
});
}
}

static void loop3_auto_test(benchmark::State &state) {
for (auto _ : state) {
loop3_auto::impl([](double a, double b, double c) {
const auto subFn = [](double x, double y) { return x / (y + 1); };
return sin(a) + log(subFn(b, c));
});
}
}

static void loop3_raw_test(benchmark::State &state) {
for (auto _ : state) {
loop3_raw::impl();
}
}

BENCHMARK(loop3_lambda_test);
BENCHMARK(loop3_function_test);
BENCHMARK(loop3_template_test);
BENCHMARK(loop3_function_arg_test);
BENCHMARK(loop3_function_2_lambda_test);
BENCHMARK(loop3_auto_test);
BENCHMARK(loop3_raw_test);
------ 本文结束 ------
------ 版权声明:转载请注明出处 ------