Mesures – Test 3.0

#include <vector>
#include <cstdlib>
#include <ctime>
#include <algorithm>
#include <iostream>
#include <chrono>
#include <random>
#include <memory>
using namespace std;
using namespace std::chrono;
struct Parent
{
   virtual long long f(int) const = 0;
   virtual ~Parent() = default;
};
struct EnfantFacto
   : Parent
{
   long long f(int n) const
   {
      long long cumul {1};
      for (int i = 1; i <= n; i++)
         cumul *= i;
      return cumul;
   }
};
struct EnfantSomme
   : Parent
{
   long long f(int n) const
   {
      long long somme {};
      for (int i = 1; i <= n; i++)
         somme += i;
      return somme;
   }
};
class OperGen
{
   long long &cumul_;
   vector<int>::const_iterator cur_;
public:
   OperGen(long long &cumul, vector<int>::const_iterator itt)
      : cumul_(cumul), cur_(itt)
   {
   }
   template <class T>
      void operator()(const T &operande)
         { cumul_ += operande.f(*cur_++); }
   long long valeur() const noexcept
      { return cumul_; }
};
class OperPol
{
   long long &cumul_;
   vector<int>::const_iterator cur_;
public:
   OperPol(long long &cumul, vector<int>::const_iterator itt)
      : cumul_(cumul), cur_(itt)
   {
   }
   void operator()(const unique_ptr<Parent> &operande)
      { cumul_ += operande->f(*cur_++); }
   long long valeur() const throw ()
      { return cumul_; }
};
int main()
{
   const int NTESTS = 10000000;
   vector<int> v(NTESTS);
   random_device rd;
   mt19937 rng(rd());
   uniform_int_distribution<int> distrib(1, 10);
   uniform_int_distribution<int> pile_face(0, 1);
   generate_n(begin(v), NTESTS, [&](){ return distrib(rng); });
   vector<EnfantFacto> veF;
   vector<EnfantSomme> veS;
   vector<unique_ptr<Parent>> vP;
   vector<int> valFac;
   vector<int> valSom;
   for (int i = 0; i < NTESTS; i++)
      if (pile_face(rng) == 0)
      {
         veF.push_back(EnfantFacto{});
         vP.push_back(unique_ptr<Parent>(new EnfantFacto));
         valFac.push_back(v[i]);
      }
      else
      {
         veS.push_back(EnfantSomme());
         vP.push_back(unique_ptr<Parent>(new EnfantSomme));
         valSom.push_back(v[i]);
      }
   clog.rdbuf(nullptr);
   long long valBidon;
   valBidon = {};
   auto poly_avant = system_clock::now();
   {
      for_each(begin(vP), end(vP), OperPol(valBidon, begin(v)));
   }
   auto poly_apres = system_clock::now();
   clog << valBidon;
   valBidon = {};
   auto gen_avant = system_clock::now();
   {
      for_each(begin(veF), end(veF), OperGen(valBidon, begin(valFac)));
      for_each(begin(veS), end(veS), OperGen(valBidon, begin(valSom)));
   }
   auto gen_apres = system_clock::now();
   clog << valBidon;
   // Résultats des tests
   cout << "Calculs sur " << NTESTS << " valeurs..." << endl
        << "\tpolymorphique: "
        << duration_cast<milliseconds>(poly_apres - poly_avant).count() << " ms." << endl
        << "\tgenerique: "
        << duration_cast<milliseconds>(gen_apres - gen_avant).count() << " ms." << endl;
}

Sur mon petit ordinateur portatif, compilé avec Visual Studio 2013, configuration Release, et en prenant bien entendu soin d'ajouter _SECURE_SCL=0 aux options du préprocesseur pour désactiver les (franchement inutiles et nuisibles) Checked Iterators, j'obtiens :

Calculs sur 10000000 valeurs...
        polymorphique: 257 ms.
        generique: 214 ms.
Appuyez sur une touche pour continuer...

Valid XHTML 1.0 Transitional

CSS Valide !