34#include <boost/program_options.hpp>
35#include <boost/python.hpp>
36#include <boost/thread.hpp>
37#include <boost/timer/timer.hpp>
40namespace po = boost::program_options;
41namespace fs = boost::filesystem;
68 po::options_description options{
"Pyston example options"};
69 options.add_options()(
"no-threads", po::value<int>()->default_value(1),
"Number of threads")(
70 "repeats", po::value<int>()->default_value(50000),
"Number of iterations inside the timing block")(
71 "file", po::value<std::string>()->default_value(
"example.py"),
"Python file to run")(
72 "dot-file", po::value<std::string>(),
"Generate a graphviz dot file with the computing graph (prefix)");
87 node.
visit(generator);
88 out << generator.
str();
99 py::object pyston = py::import(
"pyston");
100 py::dict evaluate = py::extract<py::dict>(pyston.attr(
"evaluate"));
101 py::list keys = evaluate.keys();
103 for (
int i = 0; i < py::len(keys); ++i) {
104 int nparams = py::extract<int>(keys[i]);
105 logger.
info() <<
"Found callable with " << nparams <<
" parameters";
109 py::list placeholders;
110 for (
int arg = 0; arg < nparams; ++arg) {
111 auto placeholder = std::make_shared<Placeholder<double>>(arg);
112 placeholders.append(placeholder);
116 py::object func = evaluate[nparams];
119 py::object comp_tree = func(*py::tuple(placeholders));
127 }
catch (
const py::error_already_set&) {
137 for (
int i = 0; i < n; ++i) {
138 double value = ::drand48() * 100;
139 result.first.push_back(value);
140 result.second.emplace_back(value);
148 func(*py::tuple(args));
161 for (
int nthreads = 1; nthreads <=
m_threads; ++nthreads) {
162 boost::thread_group thread_group;
163 boost::timer::cpu_timer timer;
164 for (
int n = 0; n < nthreads; ++n) {
165 thread_group.create_thread(func);
167 thread_group.join_all();
170 auto calls_per_ns = (nthreads *
m_repeats) /
static_cast<double>(timer.elapsed().wall);
171 auto calls_per_sec = calls_per_ns * 1e9;
182 for (
int nthread = 1; nthread <=
m_threads; ++nthread) {
187 for (
auto& pair : callables) {
188 logger.
info() <<
"Timing calls with " << pair.first <<
" parameters";
191 auto pyFunc = boost::bind(&
Example::runPython,
this, pair.second.first, params.first);
192 auto cppFunc = boost::bind(&
Example::runCpp,
this, pair.second.second, params.second);
195 auto measurements =
measure(pyFunc);
196 std::cout <<
"Python," << pair.first <<
",";
197 for (
int nthread = 1; nthread <=
m_threads; ++nthread) {
203 measurements =
measure(cppFunc);
204 std::cout <<
"Pyston," << pair.first <<
",";
205 for (
int nthread = 1; nthread <=
m_threads; ++nthread) {
216 if (args.
count(
"dot-file"))
222#if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION <= 6
223 PyEval_InitThreads();
228 if (!fs::exists(pyfile)) {
229 pyfile = Elements::getAuxiliaryPath(pyfile);
235 auto main_module = boost::python::import(
"__main__");
236 auto main_namespace = main_module.attr(
"__dict__");
241 py::exec_file(pyfile.native().c_str(), main_namespace);
246 }
catch (
const py::error_already_set&) {
250 return Elements::ExitCode::OK;
static Elements::Logging logger
Logger.
double world2pix(double x)
#define PYSTON_MODULE_INIT
static Logging getLogger(const std::string &name="")
void info(const std::string &logMessage)
std::pair< std::vector< double >, Arguments > createParameters(int n)
void runCpp(const std::shared_ptr< Node< double > > &node, const Arguments &args)
void runPython(boost::python::object func, const std::vector< double > &args)
void generateGraphviz(Node< double > &node, int nparams)
Elements::ExitCode mainMethod(std::map< std::string, po::variable_value > &args) override
po::options_description defineSpecificProgramOptions() override
std::map< int, std::pair< py::object, std::shared_ptr< Node< double > > > > getFunctions()
std::vector< double > measure(std::function< void(void)> func)
void registerFunction(const std::string &repr, std::function< Signature > functor)
virtual void visit(Visitor &) const =0
T emplace_back(T... args)
#define MAIN_FOR(ELEMENTS_PROGRAM_NAME)
T setprecision(T... args)