constexpr против повторных вызовов функций - PullRequest
0 голосов
/ 16 марта 2019

Я тестировал приведенный ниже код, чтобы проверить производительность constexpr. Для первой итерации результаты соответствуют ожидаемым. Но для следующих итераций нормальные вызовы функций иногда превосходят constexpr. Что мне здесь не хватает? Я ожидаю, что constexpr звонок будет лучше в любом случае. Также время, необходимое нормальной функции, также уменьшается после первой итерации. Чем можно объяснить это поведение?

Вы можете увидеть результаты кода здесь

Редактировать: Если я откомментирую строки в приведенном ниже коде, предоставляя разные значения для суммирования для каждой итерации, результаты все равно будут похожими. Вы можете увидеть его результаты здесь

Edit2: я попробовал изменения @geza и выполнил операцию для 3 миллионов для первого вызова функции и с 3 Million + i для второго вызова функции. Я ожидал, что constexpr займет очень меньше времени (почти столько же, сколько и 100), но это займет столько же времени, сколько и функция non-constexpr. Результаты ссылка

#include <iostream>
#include <chrono>

using namespace std;
using namespace std::chrono;

constexpr long long sum(const int* n){
    long long sum = 0;
    for(int i = 1; i <= *n; i++){
        sum += i;
    }
    return sum;
}

long long sum(int*  n){
    cout<<"Calling sum\n";
    long long sum = 0;
    for(int i = 1; i <= *n; i++){
        sum += i;
    }
    return sum;
}


int main(void){
    const int* p;
    int a = 100;
    p = &a;

    int *p1;
    p1 = &a;

    for(int i = 0; i < 10; i++){

        /*
        int* p1;
        int b = 100 + i; //If I uncomment the lines here are remove the 
        p1 = &b;         //earlier p1 declaration. Still the results are similar
        */

        auto start = high_resolution_clock::now(); 
        cout<<sum(p1)<<endl;
        auto stop = high_resolution_clock::now();
        cout<<"Time taken Non constexpr: "<<duration_cast<microseconds>(stop - start).count()<<endl;

        start = high_resolution_clock::now(); 
        cout<<sum(p)<<endl;
        stop = high_resolution_clock::now();
        cout<<"Time taken constexpr: "<<duration_cast<microseconds>(stop - start).count()<<endl;
    }
}

Мой код прост: создайте два указателя, один из которых постоянный (p), а другой - нет (p1). При вызове sum() с p1 вызывается функция без constexpr, что видно по выводу "Сумма вызова , а при вызове с p вызывается функция с constexpr , который можно увидеть как ничего не напечатано.

Результаты

$ g ++ -o main * .cpp
$ Главный
Вызывающая сумма
5050
Время, затраченное на неконстрпр: 63
5050
Время, затраченное constexpr: 7

Вызывающая сумма
5050
Время, затраченное на неконстрпр: 5
5050
Время, затраченное constexpr: 6
.
.
.
.
Вызов
5050
Время, затраченное на неконстрпр: 2
5050
Время, затраченное constexpr: 6

.
.
.
.
Вызывающая сумма
5050
Время, затраченное на неконстрпр: 2
5050
Время, затраченное constexpr: 2

Ответы [ 2 ]

2 голосов
/ 16 марта 2019

Ваше измерение неверно. Ваши сроки включают печать до stdout. Измените вашу программу, чтобы правильно измерить время (и удалите cout из sum):

auto start = high_resolution_clock::now(); 
auto r = sum(p1);
auto stop = high_resolution_clock::now();
cout<<r<<endl;
cout<<"Time taken Non constexpr: "<<duration_cast<microseconds>(stop - start).count()<<endl;

Вы заметите, что время будет 0 (почти) во всех случаях.

(Объяснение вашей исходной программы: кажется, что первый вызов cout << занимает больше времени, чем другие. Вероятно, cout выполняет некоторую отложенную инициализацию, поэтому первый вызов медленнее.)

И обратите внимание, поскольку вы не вызываете sum(const int *) в контексте constexpr, он будет использоваться как "нормальный" вызов функции, так же как sum(int *).

1 голос
/ 16 марта 2019

Я предлагаю вам включить оптимизацию, а затем повторно запустить тест. C ++, особенно библиотеки, зависит от оптимизации компилятора для получения кода быстрой сборки. Оптимизаторы могут убирать абстракции библиотеки и затем генерировать значительно лучший код.

Веб-сайт, на который вы ссылаетесь, позволяет изменять параметры компилятора, просто добавьте -O2, чтобы установить уровень оптимизации 2, и повторно запустите эталонный тест.

...