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)