我正在研究一個複雜的框架,它使用std::function<>
作爲許多函數的參數。通過分析我發現以下一個性能問題。可以將std :: function內聯或者我應該使用不同的方法?
有人可以解釋爲什麼Loop3a太慢嗎?我預計內聯會被使用,時間也會一樣。裝配也一樣。有什麼方法可以提高性能或改變方式嗎? C++ 17是否會以這種方式進行改變?
#include <iostream>
#include <functional>
#include <chrono>
#include <cmath>
static const unsigned N = 300;
struct Loop3a
{
void impl()
{
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 += fn(i, j, k);
}
}
}
}
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));
};
double sum;
};
struct Loop3b
{
void impl()
{
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));
}
}
}
}
double sum;
};
int main()
{
using Clock = std::chrono::high_resolution_clock;
using TimePoint = std::chrono::time_point<Clock>;
TimePoint start, stop;
Loop3a a;
Loop3b b;
start = Clock::now();
a.impl();
stop = Clock::now();
std::cout << "A: " << std::chrono::duration_cast<std::chrono::milliseconds>(stop - start).count();
std::cout << "ms\n";
start = Clock::now();
b.impl();
stop = Clock::now();
std::cout << "B: " << std::chrono::duration_cast<std::chrono::milliseconds>(stop - start).count();
std::cout << "ms\n";
return a.sum == b.sum;
}
示例輸出使用克++ 5.4用 「-O2 -std = C++ 14」:
A: 1794ms
B: 906ms
在探查我可以看到這個內部的許多:
double&& std::forward<double>(std::remove_reference<double>::type&)
std::_Function_handler<double (double, double, double), Loop3a::fn::{lambda(double, double, double)#1}>::_M_invoke(std::_Any_data const&, double, double, double)
Loop3a::fn::{lambda(double, double, double)#1}* const& std::_Any_data::_M_access<Loop3a::fn::{lambda(double, double, double)#1}*>() const
的std ::函數執行類型擦除,從不內聯。 –
恕我直言,在這種情況下,你最好配上一個函數而不是lambda。然後你可以有一個命名的函數類型,而不是'std :: function',編譯器擅長內聯函子。 – NathanOliver
使用lambda代替'std :: function'會更快嗎?即'auto fn = [](double a,double b,double c)...'。 – ilotXXI