-5

Let me start by saying, I am not a skilled C++ programmer, I have just begun that journey and am working in a Win 10 environment using Code::Blocks as my ide. I am starting to learn C++ by coding solutions to the Euler Project problems. I used these problems to start learning Python several years ago, so I have at least one Python solution for the first 50+ problems. In doing these problems in Python, I learned that as my skill improves, I can formulate better solutions. When learning Python, I used a trial & error approach to improving my code until I became aware of the python tools for timing my code. Once, I defined a convenient and consistent timing method, my coding improved dramatically. Since, I am beginning this journey now with C++ I decided I would be proactive and create a consistent method for timing the code execution. To do this, I have decided to utilize the C++ chrono library and have defined two different approaches that seemingly should produce the same time results. However as the tile to this question implies they don't.

So here's my question: Why don't the following two approaches yield the same results?

Approach # 1
This method provides a timing for the do some stuff segment of slightly over 3 seconds, but less than the CODE::BLOCKS execution time report of 3.054 seconds. I certainly understand these differences based on the program flow. So this approach seems to give good result. The issue I have with this approach is I need to copy & paste the timing code into each .cpp file I want to time, which seems sloppy.

Output using this method looks like the following:

Elapsed time in seconds : 3.00053 sec
Process returned 0 (0x0) execution time : 3.151 s

#include <iostream>
#include <chrono>
#include <unistd.h>

using namespace std;
using Clock = chrono::steady_clock;
using TimePoint = chrono::time_point<Clock>;


// Functions
TimePoint get_timestamp();
double get_duration(TimePoint, TimePoint);


int main()
{
//auto start = chrono::steady_clock::now();
auto start_t = get_timestamp();
//cout << "Start is of type " << typeid(start).name() << "\n";
// do some stuff
sleep(3);
auto end_t = get_timestamp();
//double tme_secs = chrono::duration_cast<chrono::nanoseconds>(end - start).count()/1000000000.0000;
double tme_secs = get_duration(start_t, end_t)/1000000000;
cout << "Elapsed time in seconds : " << tme_secs   << " sec";


return 0;
}

TimePoint get_timestamp(){
return Clock::now();
}


double get_duration(TimePoint start, TimePoint end){
return chrono::duration_cast<chrono::nanoseconds>(end - start).count()*1.00000000;
}

Approach #2 In this approach, I attempted to create a ProcessTime class which could be included in files that I want to time and provide a cleaner method. The problem with this approach is I get timing report in the nano seconds, which does not reflect the process being timed. Here is my implementation of this approach.

output using this method looks like the following:

Elapsed time: 1.1422e+06 seconds
Process returned 0 (0x0) execution time : 3.148 s

ProcessTime.h file

#ifndef PROCESSTIME_H_INCLUDED
#define PROCESSTIME_H_INCLUDED
#include <chrono>

using namespace std;
using Clock = chrono::steady_clock;
using TimePoint = chrono::time_point<Clock>;

class ProcessTime{
    public:
        ProcessTime();
        double get_duration();

    private:
        TimePoint proc_start;
};

#endif // PROCESSTIME_H_INCLUDED

ProcessTime.cpp file

#include "ProcessTime.h"
#include <chrono>

using namespace std;
using Clock = chrono::steady_clock;
using TimePoint = chrono::time_point<Clock>;

ProcessTime::ProcessTime(){
TimePoint proc_start = Clock::now();
}

double ProcessTime::get_duration(){
TimePoint proc_end = Clock::now();
return chrono::duration_cast<chrono::nanoseconds>(proc_end - ProcessTime::proc_start).count()*1.00000000;
 }

main.cpp file:

#include <iostream>
#include "ProcessTime.h"
#include <unistd.h>


using namespace std;

int main()
{
ProcessTime timer;
// Do some Stuff
sleep(3);

double tme_secs = timer.get_duration()/1000000000;

cout << "Elapsed time: " << tme_secs   << " seconds";
return 0;
}
itprorh66
  • 3,110
  • 4
  • 9
  • 21
  • `TimePoint proc_start = Clock::now();` -- This is a local variable. It has nothing to do with the `proc_start` that is a member of your class, it just happens to have the same name. – PaulMcKenzie Dec 05 '20 at 00:56
  • e.g use `ProcessTime::ProcessTime() : proc_start( Clock::now() ) { }` – WhozCraig Dec 05 '20 at 00:58
  • 1
    C++ is not Python. C++ is the most complicated and difficult general purpose programming in use today. I can't say whether someone can or cannot learn Python from a random web site. But I can say confidently that it's not possible to effectively learn C++ from any "become a C++ uberhacker in 24 minutes" type of a web site. The only way to learn C++ is by a guided, methodical approach in an [edited and vetted C++ textbook](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). If your goal is to gain expert level C++ knowledge, you'll need to get a textbook. – Sam Varshavchik Dec 05 '20 at 00:58
  • In addition, if you look at your output `Elapsed time: 1.1422e+06 seconds`, do you see how wild that number happens to be? That is an indication that the value was not initialized. Having numbers so out-of-whack usually indicates an uninitialized variable issue. – PaulMcKenzie Dec 05 '20 at 01:02
  • @SamVarshavchik, I happen to agree with you regarding the difficulty of C++. I have no intention of attempting to learn the language in 24 minutes, 24 days, or 24 months for that matter. I have several edited & vetted C++ textbooks that I am working through, these however only take you so far, in that the problems are geared to the level of learning, that's why I want to go through the Euler Project problems as well, since they provide a whole different perspective. – itprorh66 Dec 05 '20 at 13:50
  • Realize that the questions at those sites assume you know the language you're using fully enough to never make simple mistakes (such as the one you made here), unless it is a mistake made due to tiredness, carelessness or just a plain oversight (and you were well aware of local variable declarations). The latter reason can happen to anyone -- it's happened to me a couple of times. – PaulMcKenzie Dec 05 '20 at 13:56
  • @PaulMcKenzie, I agree, I thought the approach I took was how to initialize the variable. Subsequently, thanks to your guidance and the suggestion to learn about member initialization, I have become aware of the correct way to accomplish what I wanted. Thanks for you assistance and guidance. – itprorh66 Dec 05 '20 at 18:47

1 Answers1

3

This is incorrect:

ProcessTime::ProcessTime(){
    TimePoint proc_start = Clock::now();
}

You are setting a local variable named proc_start, and then the constructor ends. You did not set the actual member variable of ProcessTime.

One fix (and the preferred method) is to use the member-initialization list:

ProcessTime::ProcessTime() : proc_start(Clock::now()) {}

or if you knew nothing about the member-initialization list, the code would look like this to assign the value.

ProcessTime::ProcessTime(){
    proc_start = Clock::now();
}
PaulMcKenzie
  • 34,698
  • 4
  • 24
  • 45
  • Addendum: Be the envy of your peers! Be the only kid on the block who knows how to use the Member Initializer List! Be the only kid on the block who can write non-trivial C++ code! It's amazing and tragic how many people spend years getting a high quality education and come out not knowing the Member Initializer List even exists. – user4581301 Dec 05 '20 at 01:14
  • @user4581301, thanks for the tip, I will definitely check out the literature related to Member Initializer Lists. – itprorh66 Dec 05 '20 at 13:52
  • Elsewhere you wrote that you "have several edited & vetted C++ textbooks" that you are "working through". You mean tell us that not a single one of them mentions member initialization lists? Since they are one of the basic C++ concepts, every textbook presents and describes them in early chapters on classes and constructors. – Sam Varshavchik Dec 05 '20 at 14:49
  • @SamVarshavchik, I never said they didn't have information on the topic, in fact they do, the problem was I didn't recognize the fact that my problem stemmed from that particular issue, so I didn't know to look at the subject. Sometimes, you need to be smacked in the face to recognize the problem. – itprorh66 Dec 05 '20 at 15:05