Шаблоны vs функции вычисления факториала

Тема в разделе "Arduino & Shields", создана пользователем Faberge, 19 сен 2017.

  1. Faberge

    Faberge Administrator Администратор

    Прочитал тут про шаблонное программирование в C++ и задался целью проверить, насколько это позволяет эффективно переложить вычисления на компилятор. Написал простой код для Due:

    Код (C++):
    template <int n>
    struct Factorial
    {
       enum {value = n * Factorial<n-1>::value};
    };

    template<>
    struct Factorial<0>
    {
      enum {value = 1};
    };

    int factorial(int n)
    {
      if (n == 1)
      {
        return 1;
      }
      else
      {
        return n * factorial(n - 1);
      }
    }

    void setup()
    {
      // put your setup code here, to run once:
      Serial.begin(9600);
      while(!Serial)
      {
        // Do nothing
      }
    }

    void loop()
    {
      // put your main code here, to run repeatedly:
      int start_val = micros();
      Serial.print("12! = ");
      Serial.println(Factorial<12>::value);
      int end_val = micros();
      Serial.print("Loop1 time is: ");
      Serial.println(end_val - start_val);

      start_val = micros();
      Serial.print("12! = ");
      int fact = factorial(12);
      Serial.println(fact);
      end_val = micros();
      Serial.print("Loop2 time is: ");
      Serial.println(end_val - start_val);

      delay(10000);
    }
    По результатам, вычисление 12! (и отправка) с помощью шаблонов и с помощью функции занимает 35 и 37 микросекунд соответственно. Для 10! это 31 и 33 микросекунды. Больше 12! число не помещается в 32-битный int. Вопрос, это выигрыш от TMP такой мизерный или это я где-то ошибся? А может, компилятор слишком умный и функцию тоже заранее вычисляет?
     
    Последнее редактирование: 19 сен 2017
  2. rkit

    rkit Гуру

    Шаблоны ничего не вычисляют. Так близко оно только потому, что функция написана рекурсивно, что ужасно.
     
  3. Faberge

    Faberge Administrator Администратор

    Не понял, шаблоны же позволяют проводить вычисления во время компиляции кода? Или я не прав?
     
  4. rkit

    rkit Гуру

    Вычисления проводит оптимизатор. Который в arduino ide выключен. Шаблоны можно использовать как средство для генерации легкооптимизируемого кода.
     
  5. Faberge

    Faberge Administrator Администратор

    Мне кажется, вы не правы. Шаблоны же в этом коде как-то работают и результат получается правильный. Только выигрыша особо не заметно почему-то.
     
  6. b707

    b707 Гуру

    Можно и так, хотя это как микроскопом гвозди забивать.В вашем конкретном случае самым эффективным было бы заранее посчитать факториал 12 на калькуляторе :) и вписать готовую цифру в код как константу. Исполнялось бы быстрее и код короче.
    А вообще большинство программистов С++ используют шаблоны совсем не так :)
     
  7. Faberge

    Faberge Administrator Администратор

    Ну это просто пример, самый примитивный. Но мне интересно, что же происходит в этом коде на самом деле и как объяснить отсутствие видимой разницы между двумя вариантами.
     
  8. rkit

    rkit Гуру

     
  9. Faberge

    Faberge Administrator Администратор

    Вы ничего толком не объяснили и понятнее не стало.
     
  10. b707

    b707 Гуру

    Sharles, посмотрите внимательнее свой код .Кто так меряет? Вы измеряете время вычисления + два вывода в сериал. Ваши результаты ни о чем. Оставьте внутри отсечки времени только вычисления, вывод в сериал сделайте позже
     
    arkadyf нравится это.
  11. b707

    b707 Гуру

    Код перекомпонуйте
    Код (C++):
    start_val = micros();
    int fact = factorial(12);
    end_val = micros();
    Serial.print("12! = ");
    Serial.println(fact);
    Serial.print("Loop2 time is: ");
    Serial.println(end_val - start_val);
    и для второго варианта так же. Тогда результаты будут иметь хоть какой-то смысл
     
    arkadyf нравится это.
  12. Faberge

    Faberge Administrator Администратор

    Переделал код, как вы сказали, заодно вынес определение переменных из основного цикла и сделал их глобальными. Результаты получились другие: 2 и 3 мкс для шаблона и функции соответственно. Все равно для рекурсивной функции как-то слишком быстро, нет? Правда и факториал мелковат, но это же целых 10 умножений. Куда они пропали?