Тестирование кода в старых gcc-4.4.0
и gcc-4.6.4
, компилятор смог применить интеллектуальную оптимизацию и предварительно вычислить результат для входов const
:
#include <iostream>
#include <chrono>
using namespace std;
const auto N = 1000000000ULL; // constexptr is tested, no effect
unsigned long long s(unsigned long long n)
{
auto s = 0ULL;
for (auto i = 0ULL; i < n; i++)
s += i;
return s;
}
int main()
{
auto t1 = std::chrono::high_resolution_clock::now();
auto x = s(N);
auto t2 = std::chrono::high_resolution_clock::now();
auto t = std::chrono::duration_cast<std::chrono::nanoseconds>(t2-t1).count();
cout << "Result: " << x << " -- time (ms):" << t/0.1e7 << endl;
}
N
является постоянным значением, тогда компилятор может запустить функцию s
во время компиляции и присвоить результат x
. (Для N
не требуется расчет времени выполнения)
Результаты в разных версиях gcc (а также версия clang):
- Последняя версия (clang-3.4) результат (предварительно вычислен):
0.001532 ms
. - Старая версия (gcc-4.4.0) результат (предварительно рассчитанная):
0.013517 ms
. - Старая версия (gcc-4.6.4) результат (предварительно вычислен):
0.001 ms
. - Более новая версия (gcc-4.8.0 +) не вычисляет ее во время компиляции, результат:
1313.78 ms
!!.
Вопрос:
- Не оптимизирована ли эта оптимизация в 4.8.1? Почему?
- Есть ли какой-либо компилятор/переключатель для его включения (если он отключен по умолчанию)?
-
Если это опустить, как заставить компилятор выполнить этот предварительный расчет?
Примечание (1): Я тестировал оба переключателя -O2
и -O3
, никаких эффектов.
Примечание (2): Принуждение, я имею в виду команды и переключатели компилятора.
Примечание (3): Функция s
является просто примером, ее можно заменить более сложными функциями.