Image Component Library (ICL)
Classes | Public Types | Public Member Functions | List of all members
icl::utils::MultiThreader Class Reference

Utility class for parallelizing algorithms. More...

#include <MultiThreader.h>

Inheritance diagram for icl::utils::MultiThreader:
icl::utils::ShallowCopyable< MultiThreaderImpl, MultiThreaderImplDelOp >

Classes

class  Work
 plugin class for work packages performed parallel More...
 

Public Types

typedef std::vector< Work * > WorkSet
 set of work packages, that should be performed parallel More...
 
- Public Types inherited from icl::utils::ShallowCopyable< MultiThreaderImpl, MultiThreaderImplDelOp >
typedef ShallowCopyable< MultiThreaderImpl, MultiThreaderImplDelOp > ParentSC
 

Public Member Functions

 MultiThreader ()
 Empty (null) constructor. More...
 
 MultiThreader (int nThreads)
 Default constructor with defined set of working threads. More...
 
void operator() (WorkSet &ws)
 applying operator (performs each Work* element of ws parallel) More...
 
int getNumThreads () const
 returns the number of WorkThreads More...
 
- Public Member Functions inherited from icl::utils::ShallowCopyable< MultiThreaderImpl, MultiThreaderImplDelOp >
bool isNull () const
 returns wheter the objects implementation holds a null pointer More...
 

Additional Inherited Members

- Protected Member Functions inherited from icl::utils::ShallowCopyable< MultiThreaderImpl, MultiThreaderImplDelOp >
 ShallowCopyable (MultiThreaderImpl *t=0)
 create a the implementation with a given T* value More...
 
- Protected Attributes inherited from icl::utils::ShallowCopyable< MultiThreaderImpl, MultiThreaderImplDelOp >
SmartPtrBase< MultiThreaderImpl, MultiThreaderImplDelOp > impl
 shared pointer for the classes implementation More...
 

Detailed Description

Utility class for parallelizing algorithms.

Overview

The Multithreader class provides a simple interface to parallelize algorithms. To achieve a multi-threaded implementation of an algorithm, you have to split the computation loop into N parts (Work-Packages or short Work). Each of this Works will be computed in a single thread internally when given to the apply operator of the MultiThreader.
Please note This tool was written before openmp became popular and part of compilers. Today we recommend to use openmp rather then the Multithreader class.

Example

The following example explains how to parallelize a simple function-call

#include <ICLQt/Quick.h>
#include <cmath>
// a simple function calculating the l2 norm on a data array
void l2norm_vec(float *dataStart,float *dataEnd, int dimPerElem, float *dst){
for(;dataStart<dataEnd;dst++){
float accu = 0;
for(int i=0;i<dimPerElem;i++,dataStart++){
accu += (*dataStart) * (*dataStart);
}
*dst = sqrt(accu);
}
}
// Wrapper for this function (implementing the MultiThreader::Work interface)
struct L2NormWork : public MultiThreader::Work{
L2NormWork(float *dataStart,float *dataEnd, int dimPerElem, float *dst):
dataStart(dataStart),dataEnd(dataEnd),dimPerElem(dimPerElem),dst(dst){
}
float *dataStart,*dataEnd;
int dimPerElem;
float *dst;
// interface function -> calls the wrapped function
virtual void perform(){
l2norm_vec(dataStart,dataEnd,dimPerElem,dst);
}
};
int main(){
// creating some really BIG data array
const int DIM = 10000000;
// dimension of each data element
int dim = 100;
float *data = new float[DIM];
float *dst = new float[DIM/dim];
// apply single threaded 100 times:
tic();
for(int i=0;i<100;i++){
l2norm_vec(data,data+DIM,dim,dst);
}
toc();
//--- multi threaded part --------------------------
// create a MultiThreader with 2 Threads
// create a WorkSet with 2 work packages
// 1st package: first half of the array
ws[0] = new L2NormWork(data,data+DIM/2,dim,dst);
// 2nd package: second half of the array
ws[1] = new L2NormWork(data+DIM/2,data+DIM,dim,dst+DIM/2);
// apply 100 times multi-threaded in 2 Threads
tic();
for(int i=0;i<100;i++){
mt(ws);
}
toc();
// release the work instances
delete ws[0];
delete ws[1];
delete [] data;
delete [] dst;
return 0;
}

Result

The following benchmark results were obtained:

Usability

However, the MultiThreader provides a powerful interface for parallelizing code, it is still a bit inconvenient to use. The Example above has shown, that the programmer has to write about 10 additional line for the function wrapper and another 4 lines to create the WorkSet and to fill the MultiThreader instance with it.
For more convenience some additional high level classes and functions should be implemented. For instance the SplittedUnaryop class of the ICLFilter package, which provides a top level interface for parallelizing unary operators (class interface UnaryOp)

Member Typedef Documentation

◆ WorkSet

set of work packages, that should be performed parallel

Constructor & Destructor Documentation

◆ MultiThreader() [1/2]

icl::utils::MultiThreader::MultiThreader ( )

Empty (null) constructor.

◆ MultiThreader() [2/2]

icl::utils::MultiThreader::MultiThreader ( int  nThreads)

Default constructor with defined set of working threads.

Member Function Documentation

◆ getNumThreads()

int icl::utils::MultiThreader::getNumThreads ( ) const

returns the number of WorkThreads

◆ operator()()

void icl::utils::MultiThreader::operator() ( WorkSet ws)

applying operator (performs each Work* element of ws parallel)


The documentation for this class was generated from the following file: