⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 serialasync.h

📁 强大的并行科学计算软件包
💻 H
字号:
// -*- C++ -*-
// ACL:license
// This software and ancillary information (herein called "SOFTWARE")
// called Tulip is made available under the terms described
// here.  The SOFTWARE has been approved for release with associated
// LA-CC Number LA-CC-98-35.
// 
// Unless otherwise indicated, this SOFTWARE has been authored by an
// employee or employees of the University of California, operator of the
// Los Alamos National Laboratory under Contract No.  W-7405-ENG-36 with
// the U.S. Department of Energy.  The U.S. Government has rights to use,
// reproduce, and distribute this SOFTWARE, and to allow others to do so.
// The public may copy, distribute, prepare derivative works and publicly
// display this SOFTWARE without charge, provided that this Notice and
// any statement of authorship are reproduced on all copies.  Neither the
// Government nor the University makes any warranty, express or implied,
// or assumes any liability or responsibility for the use of this
// SOFTWARE.
// 
// If SOFTWARE is modified to produce derivative works, such modified
// SOFTWARE should be clearly marked, so as not to confuse it with the
// version available from LANL
// ACL:license
//-----------------------------------------------------------------------------
// This program was prepared by the Regents of the University of California
// at Los Alamos National Laboratory (the University) under Contract No. 
// W-7405-ENG-36 with the U.S. Department of Energy (DOE). The University has 
// certain rights in the program pursuant to the contract and the program 
// should not be copied or distributed outside your organization. All rights
// in the program are reserved by the DOE and the University. Neither the U.S.
// Government nor the University makes any warranty, express or implied, or
// assumes any liability or responsibility for the use of this software
//-----------------------------------------------------------------------------
// Class:
// IterateScheduler<SerialAsync>
// Iterate<SerialAsync>
// DataObject<SerialAsync>
//-----------------------------------------------------------------------------

#ifndef _SerialAsync_h_
#define _SerialAsync_h_

//////////////////////////////////////////////////////////////////////

//-----------------------------------------------------------------------------
// Overview: 
// Smarts classes for times when you want no threads but you do want
// dataflow evaluation.
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// Typedefs:
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// Includes:
//-----------------------------------------------------------------------------

#include <list>
#include <iostream.h>
#include "IterateScheduler.h"

//-----------------------------------------------------------------------------
// Forward Declarations:
//-----------------------------------------------------------------------------

inline ostream& lock(ostream& s) { return s; }
inline ostream& unlock(ostream& s) { return s; }

namespace Smarts {

//
// Tag class for specializing IterateScheduler, Iterate and DataObject.
//
struct SerialAsync 
{
  enum Action { Read, Write};
};


//-----------------------------------------------------------------------------

struct SystemContext
{
  void addNCpus(int) {}
  void wait() {}
};

extern SystemContext systemContext;

inline void concurrency(int){};
inline int concurrency() {return 1;}
inline void wait() {}

inline double StartTimer() { return 0; }
inline double StopTimer(double) { return 0; }


//-----------------------------------------------------------------------------
//
// The SerialAsync IterateScheduler, Iterate and DataObject implement a SMARTS 
// scheduler that does dataflow without threads.  What that means is that
// when you hand iterates to the IterateScheduler it stores them up until you call
// IterateScheduler::blockingEvaluate(), at which point it evaluates iterates until
// the queue is empty.
//
//-----------------------------------------------------------------------------

template<>
class IterateScheduler<SerialAsync>
{
  friend class DataObject<SerialAsync>;
  friend class Iterate<SerialAsync>;
public:

  typedef DataObject<SerialAsync> DataObject_t;
  typedef Iterate<SerialAsync> Iterate_t;

  //---------------------------------------------------------------------------
  // Constructors & Destructors;
  //---------------------------------------------------------------------------
  IterateScheduler() : generation_m(0) {}

  ~IterateScheduler() {}
  void setConcurrency(int) {};

  //---------------------------------------------------------------------------
  // Mutators.
  //---------------------------------------------------------------------------

  // Tell the scheduler that we are beginning a new generation.
  inline void beginGeneration() { ++generation_m; }

  // Tell the scheduler that we are finishing the current generation.
  inline void endGeneration() {}

  // Evaluate all the currently outstanding iterates.
  void blockingEvaluate();

  // Return the current generation.
  inline int generation() const { return generation_m; }

  // Give a class to the scheduler for later evaluation and deletion.
  inline void handOff(Iterate<SerialAsync>* it);

protected:
private:

  typedef std::list<Iterate_t*> Container_t;
  typedef Container_t::iterator Iterator_t;

  // When an iterate becomes ready for evaluation because all
  // of its data is ready, it calls this.
  inline void executable(Iterate<SerialAsync>*);

  // What generation are we in?
  int generation_m;

  // The execution queue.  Used as a FIFO.
  std::list< Iterate<SerialAsync>* > queue_m;

};

//-----------------------------------------------------------------------------

template<>
class Iterate<SerialAsync>
{
  friend class IterateScheduler<SerialAsync>;
  friend class DataObject<SerialAsync>;

public:

  typedef DataObject<SerialAsync> DataObject_t;
  typedef IterateScheduler<SerialAsync> IterateScheduler_t;

  // Construct the Iterate with:
  //   The scheduler it will inform when it is ready.
  //   The number of notifications before it is ready.
  //   Its affinity.
  inline Iterate(IterateScheduler<SerialAsync> & s, int n, int affinity=-1);

  // The dtor is virtual because the subclasses will need to add to it.
  virtual ~Iterate() {}

  // The run method does the core work of the Iterate.
  // It is supplied by the subclass.
  virtual void run() = 0;

  // Stub in all the affinities, because there is no such thing
  // in serial.
  inline int affinity() const {return 0;};
  inline int hintAffinity() const {return 0;}
  inline void affinity(int) {}
  inline void hintAffinity(int) {}

  // Receive a notification that a dependence is ready.
  inline void notify();

  // What generation is this in?
  int generation() { return generation_m; }

  // How many notifications remain?
  int notifications() const { return notifications_m; }

protected:

  // What scheduler are we working with?
  IterateScheduler<SerialAsync> &scheduler_m;

  // How many notifications should we receive before we can run?
  int notifications_m;

  // What generation is this in?
  int generation_m;

};


//-----------------------------------------------------------------------------


template<>
class DataObject<SerialAsync>
{
  friend class IterateScheduler<SerialAsync>;
  friend class Iterate<SerialAsync>;
public:

  typedef IterateScheduler<SerialAsync> IterateScheduler_t;
  typedef Iterate<SerialAsync> Iterate_t;

    // There are two ways data can be used: to read or to write.
    // Don't change this to give more than two states:
    // things inside depend on that.

    // Construct the data object with an empty set of requests
    // and the given affinity.
    inline DataObject(int affinity=-1);

    // Stub out affinity because there is no affinity in serial.
    inline int affinity() const { return 0; }
    inline void affinity(int) {}

    // An iterate makes a request for a certain action in a certain
    // generation.
    void request(Iterate<SerialAsync>&, SerialAsync::Action, int gen);

    // An iterate finishes and tells the DataObject it no longer needs
    // it.  If this is the last release for the current set of requests,
    // have the IterateScheduler release some more.
    inline void release(SerialAsync::Action);

protected:
private:

  // If release needs to let more iterates go, it calls this.
  void releaseIterates();

  // The type for a request.
  class Request
  {
  public:
    Request() {}
    Request(Iterate<SerialAsync>& it, SerialAsync::Action act) 
      : iterate_m(&it), act_m(act) {}

    Iterate<SerialAsync>& iterate() const { return *iterate_m; }
    SerialAsync::Action act() const { return act_m; }
  private:
    Iterate<SerialAsync>* iterate_m;
    SerialAsync::Action act_m;
  };

  // The type of the queue and iterator.
  typedef std::list<Request> Container_t;
  typedef Container_t::iterator Iterator_t;

  // The list of requests from various iterates.
  // They're granted in FIFO order.
  Container_t queue_m;

  // Pointer to the last request that has been granted.
  Iterator_t released_m;

  // The number of outstanding notifications.
  int notifications_m;
};

//////////////////////////////////////////////////////////////////////
//
// Inline implementation of the functions for IterateScheduler<SerialAsync>
//
//////////////////////////////////////////////////////////////////////

//
// IterateScheduler<SerialAsync>::handOff(Iterate<SerialAsync>*)
// No action needs to be taken here.  Iterates will make their
// own way into the execution queue.
//

inline void
IterateScheduler<SerialAsync>::handOff(Iterate<SerialAsync>*)
{
}

//
// IterateScheduler::executable(Iterate*)
// Put an iterate in the executable queue.
//

inline void
IterateScheduler<SerialAsync>::executable(Iterate<SerialAsync>* it)
{
  queue_m.push_front(it);
}

//////////////////////////////////////////////////////////////////////
//
// Inline implementation of the functions for Iterate<SerialAsync>
//
//////////////////////////////////////////////////////////////////////

//
// Iterate<SerialAsync>::Iterate
// Construct with the scheduler and the number of notifications.
// Ignore the affinity.
//

inline
Iterate<SerialAsync>::Iterate(IterateScheduler<SerialAsync>& s, int n, int)
: scheduler_m(s), notifications_m(n), generation_m(s.generation())
{
}

//
// Iterate<SerialAsync>::notify
// Notify the iterate that a DataObject is ready.
// Decrement the counter, and if it is zero, alert the scheduler.
//

inline void
Iterate<SerialAsync>::notify()
{
  if ( -- notifications_m == 0 )
    scheduler_m.executable(this);
}

//////////////////////////////////////////////////////////////////////
//
// Inline implementation of the functions for DataObject<SerialAsync>
//
//////////////////////////////////////////////////////////////////////

//
// DataObject::DataObject()
// Initialize:
//   released_m to the end of the queue (which should) also be the beginning.
//   notifications_m to zero, since nothing has been released yet.
//

inline
DataObject<SerialAsync>::DataObject(int)
: released_m(queue_m.end()), notifications_m(0)
{
}


//
// void DataObject::release(Action)
// An iterate has finished and is telling the DataObject that
// it is no longer needed.
//

inline void
DataObject<SerialAsync>::release(SerialAsync::Action)
{
  if ( --notifications_m == 0 )
    releaseIterates();
}

//----------------------------------------------------------------------

//
// End of Smarts namespace.
//
}

//////////////////////////////////////////////////////////////////////

//#include "IterateSchedulers/SerialAsync.cpp"

#endif     // POOMA_PACKAGE_CLASS_H

/***************************************************************************
 * $RCSfile: SerialAsync.h,v $   $Author: jac $
 * $Revision: 1.2 $   $Date: 1999/07/28 17:43:07 $
 ***************************************************************************/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -