[OpendTect_Developers] using parallel task in OpendTect

Ranojay Sen ranojay.sen at dgbes.com
Mon Jan 23 07:03:30 CET 2012


Dear All,

    OpendTect code has some inbuilt tools to handle tasks parallelly 
using multiple threads. In order to use this functionality we have to 
derive a class from ParallelTask and overrule some virtual functions and 
write the piece of code which we think should run in different threads, 
and we are ready to go. The beauty of this class is that it handles all 
the complexities of the thread handling and provides a simple  
user-friendly interface.
     In seismic interpretation horizons are everywhere, and we compute 
several features based on horizons. I was exploring what if we could use 
muti-threading //to make(or compute ) horizons. Usually when we do any 
computation on a horizon a HorSampling Iterator is used which iterates 
through all the BinIDs sequentially starting from start inline-crossline 
position. I have made a class from parallel task which will divide the 
horizon in small pieces and distribute each of these pieces to a thread 
so that each thread will process a small part of the HorSampling data 
simultaneously. This division of threads will totally be controlled by 
this class depending on the number of CPU cores on the system. Lets 
start with the class, first derive a class from ParallelTask as 
mentioned above, now overrule the virtual functions.  I guess it is time 
for a code example. This code below is very simple and self explanatory, 
I will explain some parts explicitly.

#include "arrayndimpl.h"
#include "cubesampling.h"
#include "emmanager.h"
#include "emhorizon3d.h"
#include "moddepmgr.h"
#include "progressmeter.h"
#include "ranges.h"
#include "statrand.h"
#include "executor.h"


class HorizonBuilder : public ParallelTask
{
public:
             HorizonBuilder( EM::Horizon3D* hor3d, int startinl,
                     int startcrl, float z, int nrinl,
                     int nrcrl, std::ostream& strm )
                 : hor3d_(hor3d)
                 , startinl_(startinl)
                 , startcrl_(startcrl)
                 , zed_(z)
                 , nrinl_(nrinl)
                 , nrcrl_(nrcrl)
                 , totalnr_(nrinl)
                 , progress_(*new TextStreamProgressMeter(strm))   // 
constuctor with a EM::Horizon3D* and range details.
             {
                 hor3d_->enableGeometryChecks(  false );
                 setProgressMeter( &progress_ );
             }

             ~HorizonBuilder()
             {}

     virtual od_int64    nrIterations() const { return totalnr_; }  // 
overrule the nrIteration so that the class can decide how many positions 
to process.

    virtual bool    doPrepare( int )    //create the horsampling based 
on the ranges, and fill in the horizon with undefined values.
         {
             hs_.start.inl = startinl_;
             hs_.start.crl = startcrl_;
             hs_.stop.inl = startinl_ + nrinl_;
             hs_.stop.crl = startcrl_ + nrcrl_;
             depthvals_ = new Array2DImpl<float>( hs_.nrInl()-1,
                              hs_.nrCrl() );
             const EM::SectionID sid = hor3d_->sectionID( 0 );
             hor3d_->geometry().sectionGeometry(sid)->
                        expandWithUdf( hs_.start, hs_.stop );
             return true;
         }


protected:

         virtual bool doWork( od_int64 start, od_int64 stop, int id )  
// This is the function which will split up in multiple threads. and 
will start a new thread with different HorSampling //for each thread.
         {
             HorSampling hrg( false );
             hrg.start.inl = start + startinl_;
             hrg.start.crl = startcrl_;
             hrg.stop.inl = stop + startinl_;
             hrg.stop.crl = startcrl_ + nrcrl_;
             horIter( hrg, id );
             return true;
         }

         void horIter( const HorSampling& hrg, float id )  // This 
function will actually run in parallel filling up its positions with new 
z values.
         {
             int nrdone = 0;
             HorSamplingIterator iter( hrg );
             BinID bid = hrg.start;
             const float z = id/100;
             do
             {
             int inlidx = hs_.inlIdx( bid.inl );
             int crlidx = hs_.crlIdx( bid.crl );
             depthvals_->set( inlidx, crlidx, zed_-z );
             nrdone++;

             if ( nrdone>1000 )
             {
                 addToNrDone( nrdone );
                 nrdone= 0;
             }

             } while ( iter.next(bid) );

             addToNrDone( nrdone );
         }

         virtual bool doFinish( bool success ) // finish up
         {
             const EM::SectionID sid = hor3d_->sectionID( 0 );
             const bool ret = hor3d_->setArray2D( *depthvals_, sid, 
true, 0 );
             return ret;
         }


     EM::Horizon3D*    hor3d_;
     od_int64        totalnr_;
     int            startinl_;
     int            startcrl_;
     float        zed_;
     int            nrinl_;
     int            nrcrl_;
     ProgressMeter&    progress_;
     HorSampling        hs_;
     Array2DImpl<float>* depthvals_;
};



int main( int argc, char ** argv )   // The main function  doing few 
initialisations.
{
     OD::ModDeps().ensureLoaded( "AllNonUi" );
     const EM::ObjectID objid = EM::EMM().createObject( 
EM::Horizon3D::typeStr(),
                             "Case_test" );
     EM::EMObject* emobj = EM::EMM().getObject( objid );
     mDynamicCastGet(EM::Horizon3D*,hor3d,emobj);
     if ( !hor3d )
         return 1;
     std::ostream& strm( std::cout );
     HorizonBuilder builder( hor3d, 0, 0, 1.5, 1000, 1200, strm );   // 
create the executor
     if ( !builder.execute() )  // execute
     return 1;

     strm << "\n\nSaving new horizon " << hor3d->name() << std::endl;

     PtrMan<Executor> saver = hor3d->saver();
     return saver->execute( &strm );
     return 0;
}


So that's it, a simple class to implement multi-threading. I must thank 
Kris (**Kristofer Tingdahl ) here for his guidance and inspiration for 
preparing this code. As always questions and comments are welcome.

Regards
Ranojay

-- 
Ranojay Sen
dGB Earth Sciences (India)
304, Gateway Plaza,
Hiranandani Gardens - Powai
Mumbai 400 076 - India -
Tel. +91 22 25704984 - Fax +91 22 25704977
www.dgbes.com www.opendtect.org

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.opendtect.org/pipermail/developers/attachments/20120123/e301436d/attachment.html>


More information about the Developers mailing list