YANE-Framework Tutorial 1.1.0

Tutorial page of class yane::Utils::ParallelComputing

This exammple shows the use of the ParallelComputing class. This class is used to do parallel computations without needing to create threads or schedule the computations. This example shows a simple benchmark of a computation without threads and one with the ParallelComputing class.

Introduction

The class computationmanager extends ParallelComputing and overwrites compute to provide our own functionality. The main class creates and deletes the computer, adds items that need to be computed and starts the computation. The ParallelComputing class creates the threads by its own, schedules the items and starts the computation of every thread.

Libraries

The first thing to do is to define the libraries which we require. These libraries form the head of our main program:

#include <iostream>
#include <cstdlib>

#include <yane/utils.h>

#include "simplecomputation.h"

Namespaces

Having defined the libraries which we are going to use, we now have to define the namespaces in which the classes of these libraries operate:

using namespace std;
using namespace yane::Utils;

Main Program

Optionally we need to create a Debugmaster and the computer. We also declare the tasks to compute. We don't need a struct but usually there is more than one data, therefore we will demonstrate the usual (and more difficult) way.

        yane::RTClock::RTClock *clock = new yane::RTClock::RTClock();

        DebugMasterConsole::DebugMasterConsole * debugmaster = new DebugMasterConsole::DebugMasterConsole ( clock, 90 );
        DebugClient * debugclient = debugmaster->newClient ( "Main" );

        clock->reset();
        SimpleComputation * computer = new SimpleComputation ( "Parallel Demo", debugmaster, 2 );

        SimpleComputation::T_COMPUTATIONINFO task1, task2, task3, task4;

Now we fill the threads with data and add the items to the computer. The first argument is a pointer to the task (or an int) - see below - and the secound is the weight the task has. Depending on the weight the tasks are scheduled. The longer a computation will need the higher the weight should be. (e.g. a computation needs 10 additions and another 1 then the first one should have 10 times the weight the other one has).

        task1.sleep = 0.1;
        task2.sleep = 0.9;
        task3.sleep = 0.3;
        task4.sleep = 1.0;

        // add items and start computing
        computer->addItem ( &task1, task1.sleep );
        computer->addItem ( &task2, task2.sleep );
        computer->addItem ( &task3, task3.sleep );
        computer->addItem ( &task4, task4.sleep );

The items are added, we now start the computation. The current thread is blocked until the computation is finished. After that we need to clear the items (of course it is also possible to add other items and repeat the computation).

        computer->startComputing();
        computer->clearItems();

The computation is finished, we display the needed time and clean up.

        stringstream out;
        out << "time finished: " << clock->elapsedSeconds() << ", without threads: " << ( task1.sleep + task2.sleep + task3.sleep + task4.sleep ) / 1000000.0;
        debugclient->sendDebugInfo ( out.str() );

        delete computer;
        delete clock;
        delete debugmaster;
        delete debugclient;

        return 0;

Tutorial page of the Class yane::Utils::Thread

The following struct contains the information about the computations. The tasks are created in the main function, filled there and the tasks are added to the computer. The computer schedules the tasks depending on their weight and the compute() function with the current task is called for every thread until all tasks are computed.

struct T_COMPUTATIONINFO
{
                                        int sleep;
};

The compute function contains a single computation. If a thread needs to do more than one computation, the compute function is called multiple times. First we need to cast the the pointer to the task back to the struct we used. After that we read the data and sleep for some time.

compute ( yane::Utils::ParallelComputing::T_TASKINFO * task )
{
        T_COMPUTATIONINFO * tmp = ( T_COMPUTATIONINFO * ) task->task_data.ptr;
        
        if (debugclient)
        {
                        stringstream out;
                        out << "wait: " << tmp->sleep << " sec.";
                        debugclient->sendDebugInfo ( out.str() );
        }

        usleep ( (int)(tmp->sleep*1000000.0) );
}
Author:
Michael Schamel <michael.schamel@uni-bayreuth.de>