1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
|
{% macro cpp_file() %}
#include "network.h"
#include<stdlib.h>
#include<iostream>
#include <ctime>
#include<utility>
{{ openmp_pragma('include') }}
#define Clock_epsilon 1e-14
double Network::_last_run_time = 0.0;
double Network::_last_run_completed_fraction = 0.0;
bool Network::_globally_stopped = false;
bool Network::_globally_running = false;
Network::Network()
{
t = 0.0;
}
void Network::clear()
{
objects.clear();
}
void Network::add(Clock* clock, codeobj_func func)
{
#if defined(_MSC_VER) && (_MSC_VER>=1700)
objects.push_back(std::make_pair(std::move(clock), std::move(func)));
#else
objects.push_back(std::make_pair(clock, func));
#endif
}
void Network::run(const double duration, void (*report_func)(const double, const double, const double, const double), const double report_period)
{
{% if openmp_pragma('with_openmp') %}
double start;
{% else %}
std::clock_t start, current;
{% endif %}
const double t_start = t;
const double t_end = t + duration;
double next_report_time = report_period;
// compute the set of clocks
compute_clocks();
// set interval for all clocks
for(std::set<Clock*>::iterator i=clocks.begin(); i!=clocks.end(); i++)
(*i)->set_interval(t, t_end);
{% if openmp_pragma('with_openmp') %}
start = omp_get_wtime();
{% else %}
start = std::clock();
{% endif %}
if (report_func)
{
report_func(0.0, 0.0, t_start, duration);
}
Clock* clock = next_clocks();
double elapsed_realtime;
bool did_break_early = false;
Network::_globally_running = true;
Network::_globally_stopped = false;
while(clock && clock->running() && !Network::_globally_stopped)
{
t = clock->t[0];
for(size_t i=0; i<objects.size(); i++)
{
if (report_func)
{
{% if openmp_pragma('with_openmp') %}
const double elapsed = omp_get_wtime() - start;
{% else %}
current = std::clock();
const double elapsed = ((double)(current - start) / CLOCKS_PER_SEC);
{% endif %}
if (elapsed > next_report_time)
{
report_func(elapsed, (clock->t[0]-t_start)/duration, t_start, duration);
next_report_time += report_period;
}
}
Clock *obj_clock = objects[i].first;
// Only execute the object if it uses the right clock for this step
if (curclocks.find(obj_clock) != curclocks.end())
{
codeobj_func func = objects[i].second;
if (func) // code objects can be NULL in cases where we store just the clock
func();
}
}
for(std::set<Clock*>::iterator i=curclocks.begin(); i!=curclocks.end(); i++)
(*i)->tick();
clock = next_clocks();
{% if openmp_pragma('with_openmp') %}
elapsed_realtime = omp_get_wtime() - start;
{% else %}
current = std::clock();
elapsed_realtime = (double)(current - start)/({{ openmp_pragma('get_num_threads') }} * CLOCKS_PER_SEC);
{% endif %}
{% if maximum_run_time is not none %}
if(elapsed_realtime>{{maximum_run_time}})
{
did_break_early = true;
break;
}
{% endif %}
}
Network::_globally_running = false;
if(!did_break_early && !Network::_globally_stopped)
t = t_end;
else
t = clock->t[0];
_last_run_time = elapsed_realtime;
if(duration>0)
{
_last_run_completed_fraction = (t-t_start)/duration;
} else {
_last_run_completed_fraction = 1.0;
}
if (report_func)
{
report_func(elapsed_realtime, _last_run_completed_fraction, t_start, duration);
}
}
void Network::compute_clocks()
{
clocks.clear();
for(int i=0; i<objects.size(); i++)
{
Clock *clock = objects[i].first;
clocks.insert(clock);
}
}
Clock* Network::next_clocks()
{
if (clocks.empty())
return NULL;
// find minclock, clock with smallest t value
Clock *minclock = *clocks.begin();
for(std::set<Clock*>::iterator i=clocks.begin(); i!=clocks.end(); i++)
{
Clock *clock = *i;
if(clock->t[0]<minclock->t[0])
minclock = clock;
}
// find set of equal clocks
curclocks.clear();
double t = minclock->t[0];
for(std::set<Clock*>::iterator i=clocks.begin(); i!=clocks.end(); i++)
{
Clock *clock = *i;
double s = clock->t[0];
if(s==t || fabs(s-t)<=Clock_epsilon)
curclocks.insert(clock);
}
return minclock;
}
{% endmacro %}
{% macro h_file() %}
#ifndef _BRIAN_NETWORK_H
#define _BRIAN_NETWORK_H
#include<vector>
#include<utility>
#include<set>
#include "brianlib/clocks.h"
typedef void (*codeobj_func)();
class Network
{
std::set<Clock*> clocks, curclocks;
void compute_clocks();
Clock* next_clocks();
public:
std::vector< std::pair< Clock*, codeobj_func > > objects;
double t;
static double _last_run_time;
static double _last_run_completed_fraction;
static bool _globally_stopped;
static bool _globally_running;
Network();
void clear();
void add(Clock *clock, codeobj_func func);
void run(const double duration, void (*report_func)(const double, const double, const double, const double), const double report_period);
};
#endif
{% endmacro %}
|