jeudi 2 septembre 2021

std::chrono::high_resolution_clock results get affected due the change in the code beyond the scope of the clock

I am trying to compare the run-time taken by two Library Boost and ROOT library. while doing so I am using the high resolution std::chrono::high_resolution_clock. The result's changes if I changes part of the codes which is beyond the scope of the function where the clock is. I would expect the clock's outout remains invariant.

Here is piece of code

#include <boost/histogram.hpp>
#include <random>
#include <chrono>
#include <fmt/format.h>
#include <fmt/chrono.h>
#include <iostream>
#include "TH1F.h"
#include "TH2F.h"


/*
g++ TestSpeed.C -O2 -g -ggdb $(root-config --cflags) $(root-config --libs) -lfmt -o compare -I /home/sbhawani/alice/sw/ubuntu2004_x86-64/boost/latest/include/ -I /home/sbhawani/alice/sw/ubuntu2004_x86-64/fmt/latest/include/ -L /home/sbhawani/alice/sw/ubuntu2004_x86-64/fmt/latest/lib/
*/


void compare_boost_rootOriginal()
{
  using timer = std::chrono::high_resolution_clock ;
  namespace bh = boost::histogram;
  // ===| binning |=============================================================
  const int nBins = 100;
  const float xMin = 0.;
  const float xMax = 1.;

  const size_t inputValues = 1000000;

  // ===| histograms |==========================================================
  auto h1Boost = bh::make_histogram(bh::axis::regular<>(nBins, xMin, xMax, "random"));
  TH1F h1Root = TH1F("h", ";random", nBins, xMin, xMax);

  // ===| input values |========================================================
  std::random_device rd;  // Will be used to obtain a seed for the random number engine
  std::mt19937 gen(rd()); // Standard mersenne_twister_engine seeded with rd()
  std::uniform_real_distribution<> dis(.0, 1.0);

  std::vector<float> randomValues(inputValues);
  for (auto &val : randomValues)
  {
    val = dis(gen);
  }

  // ===| fill root |===========================================================
  auto startRoot = timer::now();
  for (const auto &val : randomValues)
  {
    h1Root.Fill(val);
  }
  auto stopRoot = timer::now();
  std::chrono::duration<float> timeRoot = stopRoot - startRoot;

  // ===| fill boost |==========================================================
  auto startBoost = timer::now();
  for (const auto &val : randomValues)
  {
    h1Boost(val);
  }
  auto stopBoost = timer::now();
  std::chrono::duration<float> timeBoost = stopBoost - startBoost;

  // ===| output |==============================================================
  fmt::print("time for boost: {}, time for root: {}, ratio: {}\n", timeBoost, timeRoot, timeBoost / timeRoot);
}

void TestCheck()
{   
  const int nEvtDim = 1000000;
  const int nBins = 100;
  const float r_low = 0.0;  //general lower range of the axis
  const float r_high = 1.0; //general upper range of the axis
  using timer = std::chrono::high_resolution_clock ;
  namespace bh = boost::histogram;
  std::vector<float> Xvalues(nEvtDim);
  // ===| input values |========================================================
  std::random_device rd;  // Will be used to obtain a seed for the random number engine
  std::mt19937 gen(rd()); // Standard mersenne_twister_engine seeded with rd()
  std::uniform_real_distribution<> dis(0.0, r_high);

  for (auto &val : Xvalues)
  {
    val = dis(gen);
  }
  auto nHisto = bh::make_histogram(bh::axis::regular<>(nBins, r_low, r_high, "random"),bh::axis::regular<>(nBins, r_low, r_high, "random"));
  auto startBHn = timer::now();
  for (const auto &xval : Xvalues)
  {
    nHisto(xval,xval);
  }
  auto stopBHn = timer::now();
  std::chrono::duration<float> timeBoost = stopBHn - startBHn;

  TH2F h2D = TH2F("h2D", ";h title", nBins, r_low, r_high, nBins, r_low, r_high);
  auto startTHn = timer::now();
  for (const auto &xval : Xvalues)
  {
    h2D.Fill(xval,xval);
  }
  auto stopTHn = timer::now();
  std::chrono::duration<float> timeRoot = stopTHn - startTHn;
  fmt::print("time for boost: {}, time for root: {}, ratio: {}\n", timeBoost, timeRoot, timeBoost / timeRoot);
}


int main()
{
  compare_boost_rootOriginal();
}

I get different number(ratio of time taken by the root 1D/time taken by Boost 1D) in two scenarios

  1. run the code with commenting function void TestCheck() L65 - L102 time for boost: 0.00459109s, time for root: 0.00795637s, ratio: 0.5770334

  2. run the macro without commenting the function void TestCheck() time for boost: 0.0063973s, time for root: 0.0080162s, ratio: 0.7980463

However I don't call function void TestCheck() in the int main(). It's bit surprising that just a definition of another function body affects the clock inside another function compare_boost_rootOriginal() which has nothing to do with TestCheck().

I have not much of experience with compilers, but I would expect this number remain invariant irrespective of how I change the code outside the scope of function void compare_boost_rootOriginal()

Moreover this number also changes a lot while running the same executable several times I also would not expect the ratio change while running same executable several times.

Aucun commentaire:

Enregistrer un commentaire