10 #include <boost/numeric/ublas/io.hpp> 
   11 #include <boost/program_options.hpp> 
   12 #include <boost/foreach.hpp> 
   13 #include <boost/call_traits.hpp> 
   14 #include <boost/lexical_cast.hpp> 
   16 #include <flame/base.h> 
   17 #include <flame/state/vector.h> 
   18 #include <flame/state/matrix.h> 
   19 #include <flame/h5writer.h> 
   20 #include <flame/moment.h> 
   22 namespace po = boost::program_options;
 
   26 typedef std::vector<std::string> strvect;
 
   28 strvect tokenize(
const std::string& inp)
 
   33         size_t sep = inp.find_first_of(
',', pos);
 
   35             ret.push_back(inp.substr(pos));
 
   38             ret.push_back(inp.substr(pos, sep-pos));
 
   48 void getargs(
int argc, 
char *argv[], po::variables_map& args)
 
   50     std::ostringstream caption;
 
   51     caption<<argv[0]<<
" [options] <lattice file>";
 
   52     po::options_description opts(caption.str());
 
   54             (
"help,h", 
"Display this message")
 
   55             (
"verbose,v", po::value<int>()->default_value(0)->value_name(
"NUM"),
 
   56                 "Make some noise.  Values 0 through 6 are useful.")
 
   57             (
"define,D", po::value<std::vector<std::string> >()->composing()->value_name(
"name=type:val"),
 
   58                 "Define variable value (\"-Dname=str:value\")")
 
   59             (
"lattice", po::value<std::string>()->value_name(
"FILE"),
 
   61             (
"max,M", po::value<std::string>()->value_name(
"NUM"),
 
   62                 "Maximum number of elements propagate through. (default is all)")
 
   63             (
"format,F", po::value<std::string>()->value_name(
"FMT")->default_value(
"txt"),
 
   64                 "output format (txt or hdf5)")
 
   65             (
"select-all,A", 
"Select all elements for output")
 
   66             (
"select-type,T", po::value<std::vector<std::string> >()->composing()->value_name(
"ETYPE"),
 
   67                 "Select all elements of the given type for output")
 
   68             (
"select-name,N", po::value<std::vector<std::string> >()->composing()->value_name(
"ENAME"),
 
   69                 "Select all elements with the given name for output")
 
   70             (
"select-last,L", 
"Select last element for output")
 
   71 #ifdef CLOCK_MONOTONIC 
   72             (
"timeit", 
"Measure execution time")
 
   76     po::positional_options_description pos;
 
   77     pos.add(
"lattice", 1);
 
   79     po::store(po::command_line_parser(argc, argv).options(opts).positional(pos).run(), args);
 
   82     if(args.count(
"help") || !args.count(
"lattice")) {
 
   83         std::cout<<opts<<
"\n\n" 
   85                    " txt  - Print selected outputs states to screen ('--format txt' the default default)\n" 
   86                    "        or file ('--format txt[,file=out.txt][,verbose[=lvl#]]')\n" 
   88                    " utest - Print selected output states to screen as a python checkPropagate()\n" 
   90                    " hdf5 - Write selected output states to an HDF5 file.\n" 
   91                    "        eg. '--format hdf5,file=out.h5'\n" 
   94                    " Variable defintions made by arguments must specify a name, type, and value\n" 
   95                    " The type may be: 'str'' or 'double', which may be abbreviated as 'S' or 'D'.\n" 
   96                    " Definitions are overwritten by those in the lattice file.\n" 
  102 struct ObserverFactory
 
  104     virtual ~ObserverFactory() {}
 
  106     virtual void before_sim(
Machine&) {}
 
  107     virtual void after_sim(
Machine&) {}
 
  110 struct UnitTestObserver : 
public Observer 
  112     typedef boost::shared_ptr<std::list<std::string> > interested_t;
 
  113     interested_t interested;
 
  114     typedef std::vector<unsigned> interested_indicies_t;
 
  115     interested_indicies_t interested_indicies;
 
  117     UnitTestObserver(
const interested_t& I) :interested(I) {}
 
  118     virtual ~UnitTestObserver() {}
 
  121         typedef std::map<std::string, unsigned> lookup_t;
 
  129             case StateBase::ArrayInfo::Sizet:
 
  130                 if(info.
ndim!=0) skip = 
true;
 
  131             case StateBase::ArrayInfo::Double:
 
  136             if(info.
ndim>2) skip=
true;
 
  139             L[info.
name] = idx-1;
 
  142         interested_indicies.resize(interested->size());
 
  144         interested_t::element_type::const_iterator it = interested->begin();
 
  145         for(
size_t i=0; i<interested_indicies.size(); i++, ++it) {
 
  146             lookup_t::const_iterator Lit = L.find(*it);
 
  148                 interested_indicies[i] = Lit->second;
 
  159         if(interested_indicies.size()!=interested->size())
 
  162         std::cout<<
"    def test_"<<elem->
type_name()<<
"(self):\n" 
  163                    "        # "<<elem->
name<<
"\n" 
  164                  <<
"        self.checkPropagate(0, {}, {\n";
 
  166         for(
size_t i=0; i<interested_indicies.size(); i++) {
 
  167             unsigned idx = interested_indicies[i];
 
  169             bool valid = S->
getArray(idx, info);
 
  173             std::cout<<
"            '"<<info.
name<<
"':";
 
  176                 case StateBase::ArrayInfo::Double:
 
  177                     std::cout<<std::scientific << std::setprecision(17)<<*(
double*)info.
ptr;
 
  179                 case StateBase::ArrayInfo::Sizet:
 
  180                     std::cout<<*(
size_t*)info.
ptr;
 
  183             } 
else if(info.
ndim==1) {
 
  184                 assert(info.type==StateBase::ArrayInfo::Double);
 
  185                 std::cout<<
"asfarray([";
 
  186                 for(
size_t i=0; i<info.
dim[0]; i++) {
 
  187                     std::cout<<std::scientific << std::setprecision(16)<<*info.
get<
double>(&i);
 
  193             } 
else if(info.
ndim==2) {
 
  194                 assert(info.type==StateBase::ArrayInfo::Double);
 
  195                 std::cout<<
"asfarray([\n";
 
  196                 size_t idx[StateBase::ArrayInfo::maxdims];
 
  197                 memset(idx, 0, 
sizeof(idx));
 
  198                 for(idx[0]=0; idx[0]<info.
dim[0]; idx[0]++) {
 
  200                     for(idx[1]=0; idx[1]<info.
dim[1]; idx[1]++) {
 
  201                         std::cout<<std::scientific << std::setprecision(16)<<*info.
get<
double>(idx);
 
  202                         if(idx[1]!=info.
dim[1]-1)
 
  213         std::cout<<
"        }, max="<<elem->
index+1<<
")\n";
 
  216     struct Factory : 
public ObserverFactory
 
  218         interested_t interested;
 
  219         Factory(
const strvect& fmt) :interested(new interested_t::element_type)
 
  221             assert(!fmt.empty() && fmt[0]==
"utest");
 
  223             for(strvect::const_iterator it=fmt.begin()+1, end=fmt.end(); it!=end; ++it)
 
  225                 const std::string& cmd = *it;
 
  226                 if(cmd.find_first_of(
'=')==cmd.npos) {
 
  227                     interested->push_back(cmd);
 
  229                     std::cerr<<
"Warning: -F "<<fmt[0]<<
" includes unknown option "<<cmd<<
"\n";
 
  233         virtual ~Factory() {}
 
  236             return new UnitTestObserver(interested);
 
  241 struct StreamObserver : 
public Observer 
  245     StreamObserver(std::ostream& strm, 
int detail=1) :strm(&strm), detail(detail) {}
 
  246     virtual ~StreamObserver() {}
 
  249         (*strm)<<
"After Element ["<<elem->
index<<
"] "<<elem->
name<<
" ";
 
  250         state->
show(*strm, detail);
 
  254     struct Factory : 
public ObserverFactory
 
  256         std::auto_ptr<std::ostream> owned_strm;
 
  259         Factory(
const strvect& fmt) :strm(&
std::cout), detail(1)
 
  261             assert(!fmt.empty() && fmt[0]==
"txt");
 
  263             for(strvect::const_iterator it=fmt.begin()+1, end=fmt.end(); it!=end; ++it)
 
  265                 const std::string& cmd = *it;
 
  266                 if(cmd.substr(0,5)==
"file=") {
 
  267                     owned_strm.reset(
new std::ofstream(cmd.substr(5).c_str()));
 
  268                     strm = owned_strm.get();
 
  269                 } 
else if(cmd==
"verbose") {
 
  271                 } 
else if(cmd.substr(0,8)==
"verbose=") {
 
  272                     detail=boost::lexical_cast<
int>(cmd.substr(8));
 
  274                     std::cerr<<
"Warning: -F "<<fmt[0]<<
" includes unknown option "<<cmd<<
"\n";
 
  278         virtual ~Factory() {}
 
  281             return new StreamObserver(*strm, detail);
 
  284         virtual void after_sim(
Machine&)
 
  293     H5StateWriter *writer;
 
  294     H5Observer(H5StateWriter *writer) : writer(writer) {}
 
  295     virtual ~H5Observer() {}
 
  297     struct Factory : 
public ObserverFactory
 
  299         virtual ~Factory() {}
 
  300         std::auto_ptr<H5StateWriter> writer;
 
  301         Factory(
const strvect& fmt)
 
  303             assert(!fmt.empty() && fmt[0]==
"hdf5");
 
  305             for(strvect::const_iterator it=fmt.begin()+1, end=fmt.end(); it!=end; ++it)
 
  307                 const std::string& cmd = *it;
 
  308                 if(cmd.substr(0,5)==
"file=") {
 
  309                     writer.reset(
new H5StateWriter(cmd.substr(5)));
 
  311                     std::cerr<<
"Warning: -F "<<fmt[0]<<
" includes unknown option "<<cmd<<
"\n";
 
  315                 std::cerr<<
"Warning: hdf5 output format requires file=...\n";
 
  320             if(!writer.get()) 
return NULL;
 
  321             else              return new H5Observer(writer.get());
 
  323         virtual void before_sim(
Machine & M)
 
  325             if(writer.get()) writer->setAttr(
"sim_type", M.
simtype());
 
  327         virtual void after_sim(
Machine&)
 
  329             if(writer.get()) writer->close();
 
  336         writer->append(state);
 
  343 #ifdef CLOCK_MONOTONIC 
  344         clock_gettime(CLOCK_MONOTONIC, &ts);
 
  348 #ifdef CLOCK_MONOTONIC 
  350         clock_gettime(CLOCK_MONOTONIC, &ts);
 
  353         double D = ts.tv_nsec-start.tv_nsec;
 
  355         D += ts.tv_sec-start.tv_sec;
 
  358         return std::numeric_limits<double>::quiet_NaN();
 
  361     void showdelta(
const char *msg) {
 
  362 #ifdef CLOCK_MONOTONIC 
  364         printf(
"%s : %.3f ms\n", msg, D*1e3);
 
  371 int main(
int argc, 
char *argv[])
 
  374     po::variables_map args;
 
  375     getargs(argc, argv, args);
 
  377     bool showtime = args.count(
"timeit")>0;
 
  380     std::auto_ptr<Config> conf;
 
  382     int verb = args[
"verbose"].as<
int>();
 
  384         H5StateWriter::dontPrint();
 
  386         Machine::log_detail=(FLAME_ERROR-10*(verb-2));
 
  390         if(args.count(
"define")) {
 
  391             const std::vector<std::string>& defs = args[
"define"].as<std::vector<std::string> >();
 
  393             BOOST_FOREACH(
const std::string& def, defs) {
 
  395                 size_t equal = def.find_first_of(
'='),
 
  396                        colon = def.find_first_of(
':', equal);
 
  397                 if(equal==def.npos) {
 
  398                     std::cerr<<
"-D "<<def<<
" missing '='\n";
 
  400                 } 
else if(colon==def.npos) {
 
  401                     std::cerr<<
"-D "<<def<<
" missing ':'\n";
 
  403                 } 
else if(equal==0) {
 
  404                     std::cerr<<
"-D "<<def<<
" missing variable name\n";
 
  408                 std::string name(def.substr(0,equal)),
 
  409                             type(def.substr(equal+1, colon-equal-1)),
 
  410                            value(def.substr(colon+1));
 
  414                 if(type==
"double" || type==
"D") {
 
  415                     curval = boost::lexical_cast<
double>(value);
 
  417                 } 
else if(type==
"str" || type==
"S") {
 
  421                     std::cerr<<
"Unknown type "<<type<<
" in -D "<<def<<
"\n";
 
  430             conf.reset(P.
parse_file(args[
"lattice"].as<std::string>().c_str()));
 
  431         }
catch(std::exception& e){
 
  432             std::cerr<<
"Parse error: "<<e.what()<<
"\n";
 
  437     if(showtime) timeit.showdelta(
"Parsing");
 
  440         std::cout<<
"# Reduced lattice\n";
 
  441         GLPSPrint(std::cout, *conf);
 
  445     size_t maxelem = (size_t)-1;
 
  446     if(args.count(
"max")) {
 
  447         maxelem = boost::lexical_cast<
size_t>(args[
"max"].as<std::string>());
 
  454     std::auto_ptr<ObserverFactory> ofact;
 
  457         const std::string& ofactname = args[
"format"].as<std::string>();
 
  458         strvect fmt(tokenize(ofactname));
 
  461             std::cerr<<
"Empty output format\n";
 
  463         } 
else if(fmt[0]==
"txt") {
 
  464             ofact.reset(
new StreamObserver::Factory(fmt));
 
  465         } 
else if(fmt[0]==
"hdf5") {
 
  466             ofact.reset(
new H5Observer::Factory(fmt));
 
  467         } 
else if(fmt[0]==
"utest") {
 
  468             ofact.reset(
new UnitTestObserver::Factory(fmt));
 
  470             std::cerr<<
"Unknown output format \""<<ofactname<<
"\"\n";
 
  475     if(showtime) timeit.showdelta(
"Setup 1");
 
  479     if(showtime) timeit.showdelta(
"Create Machine");
 
  481     if(args.count(
"select-all")) {
 
  487     if(args.count(
"select-type")) {
 
  488         BOOST_FOREACH(
const std::string& etype, args[
"select-type"].as<std::vector<std::string> >()) {
 
  490             std::pair<Machine::lookup_iterator, Machine::lookup_iterator> S(sim.equal_range_type(etype));
 
  492             if(S.first==S.second) {
 
  493                 std::cerr<<
"Warning: --select-type "<<etype<<
" does not match any elements\n";
 
  495                 for(; S.first!=S.second; ++S.first) {
 
  506     if(args.count(
"select-name")) {
 
  507         BOOST_FOREACH(
const std::string& ename, args[
"select-name"].as<std::vector<std::string> >()) {
 
  509             std::pair<Machine::lookup_iterator, Machine::lookup_iterator> S(sim.equal_range(ename));
 
  511             if(S.first==S.second) {
 
  512                 std::cerr<<
"Warning: --select-name "<<ename<<
" does not match any elements\n";
 
  514                 for(; S.first!=S.second; ++S.first) {
 
  525     if(args.count(
"select-last") && sim.size()>0) {
 
  534     ofact->before_sim(sim);
 
  537         sim.set_trace(&std::cout);
 
  539         std::cout<<
"# Machine configuration\n"<<sim<<
"\n\n";
 
  542     if(showtime) timeit.showdelta(
"Setup 2");
 
  544     std::auto_ptr<StateBase> state(sim.allocState());
 
  545     if(showtime) timeit.showdelta(
"Alloc State");
 
  546     sim.propagate(state.get(), 0, maxelem);
 
  548         timeit.showdelta(
"Simulate (cache cold)");
 
  549         sim.propagate(state.get(), 0, maxelem);
 
  550         timeit.showdelta(
"Simulate (cache hot)");
 
  553     ofact->after_sim(sim);
 
  556         std::cout << 
"\n# Final " << *state << 
"\n";
 
  560     if(showtime) timeit.showdelta(
"Cleanup");
 
  563 }
catch(std::exception& e){
 
  564     std::cerr<<
"Error "<<
typeid(e).name()<<
" : "<<e.what()<<
"\n";
 
void setVar(const std::string &name, const Config::value_t &v)
Pre-define variable. 
 
virtual void show(std::ostream &, int level=0) const 
 
Base class for all simulated elements. 
 
const std::string & simtype() const 
Return the sim_type string found during construction. 
 
The core simulate Machine engine. 
 
Interface to lattice file parser. 
 
virtual const char * type_name() const =0
 
The abstract base class for all simulation state objects. 
 
Used with StateBase::getArray() to describe a single parameter. 
 
static void registeryCleanup()
Discard all registered State and Element type information. 
 
Config * parse_file(const char *fname)
Open and parse a file. 
 
const std::string name
Name of this element (unique in its Machine) 
 
size_t dim[maxdims]
Array dimensions in elements. 
 
boost::variant< double, std::vector< double >, std::string, std::vector< Config > > value_t
An individual value (double, double[], string, or Config[]) 
 
Allow inspection of intermediate State. 
 
const size_t index
Index of this element (unique in its Machine) 
 
Observer * observer() const 
The current observer, or NULL. 
 
virtual bool getArray(unsigned index, ArrayInfo &Info)
Introspect named parameter of the derived class. 
 
void set_observer(Observer *o)
 
const char * name
The parameter name. 
 
E * get(size_t *d)
Helper to fetch the pointer for a given index (assumed valid)