Почему лямбда медленнее, чем std :: function? - PullRequest
0 голосов
/ 23 ноября 2018

Я быстро написал «простой», но, надеюсь, не слишком глупый тест, чтобы проверить, не пытается ли метод всегда пытаться не назначать лямбду для std::function (потому что она медленнее? -> хотя бы для одной виртуальной функции (не уверен)) имеет смысл.

#include <iostream>
#include <functional>
#include <chrono>

typedef std::chrono::high_resolution_clock::time_point TimeVar;
#define duration(a) std::chrono::duration_cast<std::chrono::nanoseconds>(a).count()
#define timeNow() std::chrono::high_resolution_clock::now()

template<typename T, typename F>
auto time(T t, F &&rF)
{
    std::cout << t  << "\t";
    TimeVar t1=timeNow();

    int a = rand()%10;
    for(int i=0;i<10000000;i++)
    {
        a = rF(a);
    }
    auto count = duration(timeNow()-t1);
    std::cout << "a: " << a << " time: " << count << " ns " << std::endl;
    return count;
}

template<typename T>
auto timeN(T t)
{
    std::cout << t << "\t";
    TimeVar t1=timeNow();

    int a = rand()%10;
    for(int i=0;i<10000000;i++)
    {
        a = a + rand()%10;
    }
    auto count = duration(timeNow()-t1);
    std::cout << "a: " << a << " time: " << count << " ns " << std::endl;
    return count;
}


int main()
{
   auto c1 = time("lambda: ", [](int a) { return a + rand()%10; });
   auto c2 = time("std::function: ", std::function<int(int)>{[](int a) { return a + rand()%10; }}); 
   auto c3 = timeN("baseline: "); 

   std::cout << std::endl;
   std::cout << "lambda: \t" << (float)c1/c3  << " x slower then baseline" << std::endl;
   std::cout << "std::function: \t" << (float)c2/c3  << " x slower then baseline" << std::endl;

   std::cout << "std::function: \t" << (float)c2/c1  << " x slower then lambda" << std::endl;
}

Live

Вывод:

lambda:     a: 45011713 time: 182743890 ns 
std::function:  a: 45000320 time: 161290160 ns 
baseline:   a: 45004251 time: 134701347 ns 

lambda:     1.35666 x slower then baseline
std::function:  1.19739 x slower then baseline
std::function:  0.882602 x slower then lambda

Это озадачивает меня, поскольку лямбда медленнее, чем std ::функция.Зачем?Я имею в виду, что тип лямбды генерируется компилятором, и я предположил, что он может оптимизировать намного больше, чем непрозрачный тип std :: function.(если вы компилируете с помощью clang, вы получите противоположный результат).Также возникает вопрос, почему функция std :: работает так быстро, если ее непрозрачный тип ...?Является ли назначение особенным для лямбд и оптимизировано?

1 Ответ

0 голосов
/ 23 ноября 2018

Нет большой разницы, если вы включите оптимизацию:

~$ g++ -O3 --std=c++14 a.cpp
~$ ./a.out
lambda:     a: 45002817 time: 63951040 ns
std::function:  a: 45002682 time: 64764776 ns
baseline:   a: 44990972 time: 62371825 ns

lambda:     1.02532 x slower then baseline
std::function:  1.03837 x slower then baseline
std::function:  1.01272 x slower then lambda
~$ ./a.out
lambda:     a: 45002817 time: 63315194 ns
std::function:  a: 45002682 time: 63703902 ns
baseline:   a: 44990972 time: 64156841 ns

lambda:     0.986881 x slower then baseline
std::function:  0.99294 x slower then baseline
std::function:  1.00614 x slower then lambda
~$ ./a.out
lambda:     a: 45002817 time: 64336198 ns
std::function:  a: 45002682 time: 64334809 ns
baseline:   a: 44990972 time: 62341043 ns

lambda:     1.032 x slower then baseline
std::function:  1.03198 x slower then baseline
std::function:  0.999978 x slower then lambda
~$ ./a.out
lambda:     a: 45002817 time: 64270878 ns
std::function:  a: 45002682 time: 63267123 ns
baseline:   a: 44990972 time: 62374261 ns

lambda:     1.03041 x slower then baseline
std::function:  1.01431 x slower then baseline
std::function:  0.984382 x slower then lambda
~$ ./a.out
lambda:     a: 45002817 time: 63049074 ns
std::function:  a: 45002682 time: 65208456 ns
baseline:   a: 44990972 time: 62404926 ns

lambda:     1.01032 x slower then baseline
std::function:  1.04492 x slower then baseline
std::function:  1.03425 x slower then lambda
~$ ./a.out
lambda:     a: 45002817 time: 67177288 ns
std::function:  a: 45002682 time: 65373651 ns
baseline:   a: 44990972 time: 63936167 ns

lambda:     1.05069 x slower then baseline
std::function:  1.02248 x slower then baseline
std::function:  0.973151 x slower then lambda
...