TPIE

v1.1rc1-6-g0c97303
Progress reporting

TPIE has a couple classes for reporting progress to the user.

The central concept is the progress_indicator, fleshed out in tpie::progress_indicator_base. A progress indicator must have the methods init(stream_size_type steps), step() and done(). It should inherit from the virtual base class tpie::progress_indicator_base.

The simplest way of reporting progress is settling on a concrete progress indicator, for instance tpie::progress_indicator_arrow, and passing around pointers or references to this in your code. You may then call init() once with the number of items to process and step() for each item and finally done() when you have completed processing. The following piece of code is from the file example/helloworld.cpp (albeit slightly modified).

void populate_stream(tpie::file_stream<size_t> & writer) {
// The parameter to init tells the PI how many times we will call step().
tpie::progress_indicator_arrow progress_writer("Populate stream", s);
progress_writer.init(s);
for (size_t i = 0; i < s; ++i) {
// Write a single item
writer.write((i * y) % s);
progress_writer.step();
}
progress_writer.done();
}

Fractional progress reporting

Often, you will divide your algorithm into several sequential steps. In this case, you may choose to have more than one progress indicator. If you wish to display just a single progress bar showing the total progress towards the goal, TPIE provides a fractional progress indicator implementation.

A fractional progress indicator wraps another progress indicator and provides as many fractional subindicators as the user needs. A fractional subindicator adheres to the progress indicator concept. Behind the scenes, the fractional progress indicator measures the time it takes each step of the algorithm to complete. Using the execution time predictor, over several runs of the algorithm it will become better at predicting the amount of time each subindicator spends. In the simplest case, a program will first write items to a stream, and then read them back. Using a fractional progress indicator, TPIE will eventually figure out the ratio of time spent between reading and writing. Eventually, the amount of progress reported to the user will increase linearly with wall clock time.

The following example is taken from the file example/helloworld.cpp.

progress_indicator_arrow pi("Hello world", elements);
fractional_progress fp(&pi);
fractional_subindicator progress_writer(fp, "Writer", TPIE_FSI, elements, "Writer");
fractional_subindicator progress_sort(fp, "Sort", TPIE_FSI, elements, "Sort");
fp.init();
write_number_stream(progress_writer);
sort_number_stream(progress_sort);
fp.done();

Disabling progress reporting

There are two ways in which you may optionally disable progress reporting at runtime.

The first is polymorphically. If you pass around pointers to the progress_indicator_base class, you may instantiate tpie::progress_indicator_null rather than, say, tpie::progress_indicator_arrow. This is a virtual null object implementation of the progress indicator base class. Although no progress is reported, you still pay the price of a virtual method call for each call to step().

The second is using templates. TPIE provides a light-weight null object implementation of the progress indicator concept called tpie::dummy_progress_indicator. This, in conjunction with the tpie::progress_types helper class and a boolean template parameter indicating whether to report progress or not, allows you to generate two versions of code at compile time: One with progress enabled, and one without.

#include <tpie/types.h>
tpie::uint64_t item_count;
template <bool use_progress>
void scanner(typename tpie::progress_types<use_progress>::base * pi) {
pi->init(item_count);
for (tpie::uint64_t i = 0; i < item_count; ++i) {
fs.read();
pi->step();
}
pi->done();
}
void scanner_optional_progress(bool use_progress) {
if (use_progress) {
tpie::progress_indicator_arrow pi("Hello world", item_count);
scanner<true>(&pi);
} else {
scanner<false>(&pi);
}
}

Since dummy_progress_indicator has non-virtual, inline implementations of the init, step and done methods, we save a lot of CPU work at run time when the user wishes to disable progress reporting. However, twice the amount of code is generated, which may lead to more frequent cache misses, which can incur performance penalty at run time.