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/moment.h>
22 #include <flame/h5writer.h>
25 namespace po = boost::program_options;
29 typedef std::vector<std::string> strvect;
31 strvect tokenize(
const std::string& inp)
36 size_t sep = inp.find_first_of(
',', pos);
38 ret.push_back(inp.substr(pos));
41 ret.push_back(inp.substr(pos, sep-pos));
51 void getargs(
int argc,
char *argv[], po::variables_map& args)
53 std::ostringstream caption;
54 caption<<argv[0]<<
" [options] <lattice file>";
55 po::options_description opts(caption.str());
57 (
"help,h",
"Display this message")
58 (
"verbose,v", po::value<int>()->default_value(0)->value_name(
"NUM"),
59 "Make some noise. Values 0 through 6 are useful.")
60 (
"define,D", po::value<std::vector<std::string> >()->composing()->value_name(
"name=type:val"),
61 "Define variable value (\"-Dname=str:value\")")
62 (
"lattice", po::value<std::string>()->value_name(
"FILE"),
64 (
"max,M", po::value<std::string>()->value_name(
"NUM"),
65 "Maximum number of elements propagate through. (default is all)")
67 (
"format,F", po::value<std::string>()->value_name(
"FMT")->default_value(
"txt"),
68 "output format (txt or hdf5)")
70 (
"format,F", po::value<std::string>()->value_name(
"FMT")->default_value(
"txt"),
71 "output format (txt)")
73 (
"select-all,A",
"Select all elements for output")
74 (
"select-type,T", po::value<std::vector<std::string> >()->composing()->value_name(
"ETYPE"),
75 "Select all elements of the given type for output")
76 (
"select-name,N", po::value<std::vector<std::string> >()->composing()->value_name(
"ENAME"),
77 "Select all elements with the given name for output")
78 (
"select-last,L",
"Select last element for output")
79 #ifdef CLOCK_MONOTONIC
80 (
"timeit",
"Measure execution time")
84 po::positional_options_description pos;
85 pos.add(
"lattice", 1);
87 po::store(po::command_line_parser(argc, argv).options(opts).positional(pos).run(), args);
90 if(args.count(
"help") || !args.count(
"lattice")) {
91 std::cout<<opts<<
"\n\n"
93 " txt - Print selected outputs states to screen ('--format txt' the default default)\n"
94 " or file ('--format txt[,file=out.txt][,verbose[=lvl#]]')\n"
96 " utest - Print selected output states to screen as a python checkPropagate()\n"
99 " hdf5 - Write selected output states to an HDF5 file.\n"
100 " eg. '--format hdf5,file=out.h5'\n"
104 " Variable defintions made by arguments must specify a name, type, and value\n"
105 " The type may be: 'str'' or 'double', which may be abbreviated as 'S' or 'D'.\n"
106 " Definitions are overwritten by those in the lattice file.\n"
112 struct ObserverFactory
114 virtual ~ObserverFactory() {}
116 virtual void before_sim(
Machine&) {}
117 virtual void after_sim(
Machine&) {}
120 struct UnitTestObserver :
public Observer
122 typedef boost::shared_ptr<std::list<std::string> > interested_t;
123 interested_t interested;
124 typedef std::vector<unsigned> interested_indicies_t;
125 interested_indicies_t interested_indicies;
127 UnitTestObserver(
const interested_t& I) :interested(I) {}
128 virtual ~UnitTestObserver() {}
131 typedef std::map<std::string, unsigned> lookup_t;
139 case StateBase::ArrayInfo::Sizet:
140 if(info.
ndim!=0) skip =
true;
141 case StateBase::ArrayInfo::Double:
146 if(info.
ndim>2) skip=
true;
149 L[info.
name] = idx-1;
152 interested_indicies.resize(interested->size());
154 interested_t::element_type::const_iterator it = interested->begin();
155 for(
size_t i=0; i<interested_indicies.size(); i++, ++it) {
156 lookup_t::const_iterator Lit = L.find(*it);
158 interested_indicies[i] = Lit->second;
169 if(interested_indicies.size()!=interested->size())
172 std::cout<<
" def test_"<<elem->
type_name()<<
"(self):\n"
173 " # "<<elem->
name<<
"\n"
174 <<
" self.checkPropagate(0, {}, {\n";
176 for(
size_t i=0; i<interested_indicies.size(); i++) {
177 unsigned idx = interested_indicies[i];
179 bool valid = S->
getArray(idx, info);
183 std::cout<<
" '"<<info.
name<<
"':";
186 case StateBase::ArrayInfo::Double:
187 std::cout<<std::scientific << std::setprecision(17)<<*(
double*)info.
ptr;
189 case StateBase::ArrayInfo::Sizet:
190 std::cout<<*(
size_t*)info.
ptr;
193 }
else if(info.
ndim==1) {
194 assert(info.type==StateBase::ArrayInfo::Double);
195 std::cout<<
"asfarray([";
196 for(
size_t i=0; i<info.
dim[0]; i++) {
197 std::cout<<std::scientific << std::setprecision(16)<<*info.
get<
double>(&i);
203 }
else if(info.
ndim==2) {
204 assert(info.type==StateBase::ArrayInfo::Double);
205 std::cout<<
"asfarray([\n";
206 size_t idx[StateBase::ArrayInfo::maxdims];
207 memset(idx, 0,
sizeof(idx));
208 for(idx[0]=0; idx[0]<info.
dim[0]; idx[0]++) {
210 for(idx[1]=0; idx[1]<info.
dim[1]; idx[1]++) {
211 std::cout<<std::scientific << std::setprecision(16)<<*info.
get<
double>(idx);
212 if(idx[1]!=info.
dim[1]-1)
223 std::cout<<
" }, max="<<elem->
index+1<<
")\n";
226 struct Factory :
public ObserverFactory
228 interested_t interested;
229 Factory(
const strvect& fmt) :interested(new interested_t::element_type)
231 assert(!fmt.empty() && fmt[0]==
"utest");
233 for(strvect::const_iterator it=fmt.begin()+1, end=fmt.end(); it!=end; ++it)
235 const std::string& cmd = *it;
236 if(cmd.find_first_of(
'=')==cmd.npos) {
237 interested->push_back(cmd);
239 std::cerr<<
"Warning: -F "<<fmt[0]<<
" includes unknown option "<<cmd<<
"\n";
243 virtual ~Factory() {}
246 return new UnitTestObserver(interested);
251 struct StreamObserver :
public Observer
255 StreamObserver(std::ostream& strm,
int detail=1) :strm(&strm), detail(detail) {}
256 virtual ~StreamObserver() {}
259 (*strm)<<
"After Element ["<<elem->
index<<
"] "<<elem->
name<<
" ";
260 state->
show(*strm, detail);
264 struct Factory :
public ObserverFactory
266 std::unique_ptr<std::ostream> owned_strm;
269 Factory(
const strvect& fmt) :strm(&std::cout), detail(1)
271 assert(!fmt.empty() && fmt[0]==
"txt");
273 for(strvect::const_iterator it=fmt.begin()+1, end=fmt.end(); it!=end; ++it)
275 const std::string& cmd = *it;
276 if(cmd.substr(0,5)==
"file=") {
277 owned_strm.reset(
new std::ofstream(cmd.substr(5).c_str()));
278 strm = owned_strm.get();
279 }
else if(cmd==
"verbose") {
281 }
else if(cmd.substr(0,8)==
"verbose=") {
282 detail=boost::lexical_cast<
int>(cmd.substr(8));
284 std::cerr<<
"Warning: -F "<<fmt[0]<<
" includes unknown option "<<cmd<<
"\n";
288 virtual ~Factory() {}
291 return new StreamObserver(*strm, detail);
294 virtual void after_sim(
Machine&)
304 H5StateWriter *writer;
305 H5Observer(H5StateWriter *writer) : writer(writer) {}
306 virtual ~H5Observer() {}
308 struct Factory :
public ObserverFactory
310 virtual ~Factory() {}
311 std::unique_ptr<H5StateWriter> writer;
312 Factory(
const strvect& fmt)
314 assert(!fmt.empty() && fmt[0]==
"hdf5");
316 for(strvect::const_iterator it=fmt.begin()+1, end=fmt.end(); it!=end; ++it)
318 const std::string& cmd = *it;
319 if(cmd.substr(0,5)==
"file=") {
320 writer.reset(
new H5StateWriter(cmd.substr(5)));
322 std::cerr<<
"Warning: -F "<<fmt[0]<<
" includes unknown option "<<cmd<<
"\n";
326 std::cerr<<
"Warning: hdf5 output format requires file=...\n";
331 if(!writer.get())
return NULL;
332 else return new H5Observer(writer.get());
334 virtual void before_sim(
Machine & M)
336 if(writer.get()) writer->setAttr(
"sim_type", M.
simtype());
338 virtual void after_sim(
Machine&)
340 if(writer.get()) writer->close();
347 writer->append(state);
355 #ifdef CLOCK_MONOTONIC
356 clock_gettime(CLOCK_MONOTONIC, &ts);
360 #ifdef CLOCK_MONOTONIC
362 clock_gettime(CLOCK_MONOTONIC, &ts);
365 double D = ts.tv_nsec-start.tv_nsec;
367 D += ts.tv_sec-start.tv_sec;
370 return std::numeric_limits<double>::quiet_NaN();
373 void showdelta(
const char *msg) {
374 #ifdef CLOCK_MONOTONIC
376 printf(
"%s : %.3f ms\n", msg, D*1e3);
383 int main(
int argc,
char *argv[])
386 po::variables_map args;
387 getargs(argc, argv, args);
389 bool showtime = args.count(
"timeit")>0;
392 std::unique_ptr<Config> conf;
394 int verb = args[
"verbose"].as<
int>();
397 H5StateWriter::dontPrint();
400 Machine::log_detail=(FLAME_ERROR-10*(verb-2));
404 if(args.count(
"define")) {
405 const std::vector<std::string>& defs = args[
"define"].as<std::vector<std::string> >();
407 BOOST_FOREACH(
const std::string& def, defs) {
409 size_t equal = def.find_first_of(
'='),
410 colon = def.find_first_of(
':', equal);
411 if(equal==def.npos) {
412 std::cerr<<
"-D "<<def<<
" missing '='\n";
414 }
else if(colon==def.npos) {
415 std::cerr<<
"-D "<<def<<
" missing ':'\n";
417 }
else if(equal==0) {
418 std::cerr<<
"-D "<<def<<
" missing variable name\n";
422 std::string name(def.substr(0,equal)),
423 type(def.substr(equal+1, colon-equal-1)),
424 value(def.substr(colon+1));
428 if(type==
"double" || type==
"D") {
429 curval = boost::lexical_cast<
double>(value);
431 }
else if(type==
"str" || type==
"S") {
435 std::cerr<<
"Unknown type "<<type<<
" in -D "<<def<<
"\n";
444 conf.reset(P.
parse_file(args[
"lattice"].as<std::string>().c_str()));
445 }
catch(std::exception& e){
446 std::cerr<<
"Parse error: "<<e.what()<<
"\n";
451 if(showtime) timeit.showdelta(
"Parsing");
454 std::cout<<
"# Reduced lattice\n";
455 GLPSPrint(std::cout, *conf);
463 int maxelem = INT_MAX;
464 if(args.count(
"max")) {
465 maxelem = boost::lexical_cast<
int>(args[
"max"].as<std::string>());
472 std::unique_ptr<ObserverFactory> ofact;
475 const std::string& ofactname = args[
"format"].as<std::string>();
476 strvect fmt(tokenize(ofactname));
479 std::cerr<<
"Empty output format\n";
481 }
else if(fmt[0]==
"txt") {
482 ofact.reset(
new StreamObserver::Factory(fmt));
484 }
else if(fmt[0]==
"hdf5") {
485 ofact.reset(
new H5Observer::Factory(fmt));
487 }
else if(fmt[0]==
"utest") {
488 ofact.reset(
new UnitTestObserver::Factory(fmt));
490 std::cerr<<
"Unknown output format \""<<ofactname<<
"\"\n";
495 if(showtime) timeit.showdelta(
"Setup 1");
499 if(showtime) timeit.showdelta(
"Create Machine");
501 if(args.count(
"select-all")) {
507 if(args.count(
"select-type")) {
508 BOOST_FOREACH(
const std::string& etype, args[
"select-type"].as<std::vector<std::string> >()) {
510 std::pair<Machine::lookup_iterator, Machine::lookup_iterator> S(sim.equal_range_type(etype));
512 if(S.first==S.second) {
513 std::cerr<<
"Warning: --select-type "<<etype<<
" does not match any elements\n";
515 for(; S.first!=S.second; ++S.first) {
526 if(args.count(
"select-name")) {
527 BOOST_FOREACH(
const std::string& ename, args[
"select-name"].as<std::vector<std::string> >()) {
529 std::pair<Machine::lookup_iterator, Machine::lookup_iterator> S(sim.equal_range(ename));
531 if(S.first==S.second) {
532 std::cerr<<
"Warning: --select-name "<<ename<<
" does not match any elements\n";
534 for(; S.first!=S.second; ++S.first) {
545 if(args.count(
"select-last") && sim.size()>0) {
554 ofact->before_sim(sim);
557 sim.set_trace(&std::cout);
559 std::cout<<
"# Machine configuration\n"<<sim<<
"\n\n";
562 if(showtime) timeit.showdelta(
"Setup 2");
564 std::unique_ptr<StateBase> state(sim.allocState());
565 if(showtime) timeit.showdelta(
"Alloc State");
566 sim.propagate(state.get(), 0, maxelem);
568 timeit.showdelta(
"Simulate (cache cold)");
569 sim.propagate(state.get(), 0, maxelem);
570 timeit.showdelta(
"Simulate (cache hot)");
573 ofact->after_sim(sim);
576 std::cout <<
"\n# Final " << *state <<
"\n";
580 if(showtime) timeit.showdelta(
"Cleanup");
583 }
catch(std::exception& e){
584 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.
Config * parse_file(const char *fname, const bool have_lattice=true)
Open and parse a file.
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.
size_t index
Index of this element (unique in its Machine)
static void registeryCleanup()
Discard all registered State and Element type information.
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.
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)