2 #include <../../nrnconf.h>
9 #include <unordered_map>
13 #define MD 2147483648.
27 #define BGP_INTERVAL 2
52 extern void nrn_fake_fire(
int gid,
double firetime,
int fake_out);
76 std::vector<int>& spikegidvec);
91 extern void nrnmpi_split_clear();
99 #include "../nrnmpi/mpispike.h"
101 void nrn_timeout(
int);
105 void nrn2ncs_outputevent(
int netcon_output_index,
double firetime);
106 bool nrn_use_compress_;
107 #define use_compress_ nrn_use_compress_
110 extern int ncs_bgp_sending_info(
int**);
111 extern int ncs_bgp_target_hosts(
int,
int**);
112 extern int ncs_bgp_target_info(
int**);
113 extern int ncs_bgp_mindelays(
int**,
double**);
116 int ncs_netcon_mindelays(
int** hosts,
double** delays) {
117 return ncs_bgp_mindelays(hosts, delays);
120 double ncs_netcon_localmindelay(
int srcgid) {
126 int ncs_netcon_count(
int srcgid,
bool localNetCons) {
128 const auto& iter =
map.find(srcgid);
129 PreSyn* ps{iter !=
map.end() ? iter->second :
nullptr};
132 fprintf(stderr,
"should never happen!\n");
136 return ps->
dil_.count();
140 void ncs_netcon_inject(
int srcgid,
int netconIndex,
double spikeTime,
bool localNetCons) {
143 const auto& iter =
map.find(srcgid);
144 PreSyn* ps{iter !=
map.end() ? iter->second :
nullptr};
161 int ncs_gid_receiving_info(
int** presyngids) {
162 return ncs_bgp_target_info(presyngids);
166 int ncs_gid_sending_count(
int** sendlist2build) {
167 return ncs_bgp_sending_info(sendlist2build);
170 int ncs_target_hosts(
int gid,
int** targetnodes) {
171 return ncs_bgp_target_hosts(gid, targetnodes);
177 bool nrn_use_localgid_;
178 void nrn_outputevent(
unsigned char localgid,
double firetime);
179 static std::vector<std::unique_ptr<Gid2PreSyn>> localmaps_;
182 static int nsend_, nsendmax_, nrecv_, nrecv_useful_;
187 static int ocapacity_;
191 static int spfixout_capacity_;
193 static void nrn_spike_exchange_compressed(
NrnThread*);
319 inline static void sppk(
unsigned char*
c,
int gid) {
325 inline static int spupk(
unsigned char*
c) {
334 void nrn_outputevent(
unsigned char localgid,
double firetime) {
342 if (idxout_ >= spfixout_capacity_) {
343 spfixout_capacity_ *= 2;
345 spfixout_capacity_ *
sizeof(
unsigned char));
356 void nrn2ncs_outputevent(
int gid,
double firetime) {
365 if (idxout_ >= spfixout_capacity_) {
366 spfixout_capacity_ *= 2;
368 spfixout_capacity_ *
sizeof(
unsigned char));
379 #if nrn_spikebuf_size == 0
381 if (
i >= ocapacity_) {
393 if (
i >= ocapacity_) {
402 spbufout_->gid[
i] = gid;
403 spbufout_->spiketime[
i] = firetime;
442 #if BGPDMA && (BGP_INTERVAL == 2)
480 hoc_execerror(
"usable mindelay is 0",
"(or less than dt for fixed step method)");
523 #if nrn_spikebuf_size > 0
525 spbufout_->nspike = 0;
530 nsend_ = nsendmax_ = nrecv_ = nrecv_useful_ = 0;
559 nrn_spike_exchange_compressed(nt);
570 if (nsendmax_ <
nout_) {
574 #if nrn_spikebuf_size > 0
575 spbufout_->nspike =
nout_;
582 n = nrnmpi_spike_exchange();
587 tbuf_[itbuf_++] = (
unsigned long)
nout_;
588 tbuf_[itbuf_++] = (
unsigned long)
n;
598 if (max_histogram_) {
606 if (max_histogram_) {
610 #if nrn_spikebuf_size == 0
615 if (mx < spbufin_[
i].nspike) {
616 mx = spbufin_[
i].nspike;
622 mx = (mx <
ms) ? mx :
ms;
626 #if nrn_spikebuf_size > 0
629 int nn = spbufin_[
i].nspike;
633 for (
j = 0;
j < nn; ++
j) {
634 auto iter =
gid2in_.find(spbufin_[
i].gid[
j]);
636 PreSyn* ps = iter->second;
646 for (
i = 0;
i <
n; ++
i) {
649 PreSyn* ps = iter->second;
660 void nrn_spike_exchange_compressed(
NrnThread* nt) {
673 if (nsendmax_ <
nout_) {
686 n = nrnmpi_spike_exchange_compressed();
691 tbuf_[itbuf_++] = (
unsigned long)
nout_;
692 tbuf_[itbuf_++] = (
unsigned long)
n;
702 if (max_histogram_) {
711 if (max_histogram_) {
721 mx = (mx <
ms) ? mx :
ms;
725 if (nrn_use_localgid_) {
744 for (
j = 0;
j < nnn; ++
j) {
749 auto iter = gps->find(lgid);
750 if (iter != gps->end()) {
751 PreSyn* ps = iter->second;
758 for (;
j < nn; ++
j) {
762 auto iter = gps->find(lgid);
763 if (iter != gps->end()) {
764 PreSyn* ps = iter->second;
781 for (
j = 0;
j < nn; ++
j) {
788 PreSyn* ps = iter->second;
798 for (
i = 0;
i <
n; ++
i) {
804 PreSyn* ps = iter->second;
817 static void mk_localgid_rep() {
833 nrn_use_localgid_ =
true;
837 int* sbuf =
new int[ngidmax + 1];
846 ps->localgid_ = (
unsigned char) ngid;
872 sbuf = rbuf +
i * (ngidmax + 1);
874 for (
int k = 0;
k < ngid; ++
k) {
875 auto iter =
gid2in_.find(
int(sbuf[
k]));
877 PreSyn* ps = iter->second;
878 (*localmaps_[
i])[
k] = ps;
917 }
else if (fake_out && !ps) {
942 #if nrn_spikebuf_size > 0
943 spbufout_ = (NRNMPI_Spikebuf*)
hoc_Emalloc(
sizeof(NRNMPI_Spikebuf));
962 sprintf(m,
"gid=%d already exists as an input port", gid);
964 m,
"Setup all the output ports on this process before using them as input ports.");
967 sprintf(m,
"gid=%d already exists on this process as an output port", gid);
998 nrnmpi_split_clear();
1004 if (
arg == 2 ||
arg == 3) {
1009 PreSyn* ps = iter.second;
1019 if (ps->
dil_.empty()) {
1025 for (
const auto& iter:
gid2in_) {
1026 PreSyn* ps = iter.second;
1035 if (ps->
dil_.empty()) {
1049 PreSyn* ps = iter->second;
1067 hoc_execerror(
"gid not associated with spike generation location", 0);
1069 PreSyn* ps = iter->second;
1081 sprintf(
buf,
"gid=%d is in the input list. Must register prior to connecting", gid);
1109 PreSyn* ps = iter->second;
1121 PreSyn* ps = iter->second;
1123 ps->
record(spikevec, gidvec, gid);
1128 PreSyn* ps = iter.second;
1142 for (
int i = 0;
i < sz; ++
i) {
1143 int gid = int(pd[
i]);
1146 PreSyn* ps = iter->second;
1148 ps->
record(spikevec, gidvec, gid);
1157 PreSyn* ps = iter->second;
1174 PreSyn* ps = iter->second;
1202 auto iter_out =
gid2out_.find(gid);
1205 ps = iter_out->second;
1212 auto iter_in =
gid2in_.find(gid);
1213 if (iter_in !=
gid2in_.end()) {
1215 ps = iter_in->second;
1234 nc = (
NetCon*) ((*po)->u.this_pointer);
1236 hoc_execerror(
"target is different from 3rd arg NetCon target", 0);
1240 nc =
new NetCon(ps, target);
1281 hoc_execerror(
"mindelay is 0",
"(or less than dt for fixed step method)");
1301 #if BGP_INTERVAL == 2
1330 std::vector<int>& spikegidvec) {
1331 assert(spiketvec.size() == spikegidvec.size());
1332 if (spiketvec.size()) {
1344 spikegidvec.begin(),
1348 for (
size_t i = 0;
i < spikegidvec.size(); ++
i) {
1349 auto iter =
gid2out_.find(spikegidvec[
i]);
1351 PreSyn* ps = iter->second;
1377 for (
const auto& iter:
gid2in_) {
1378 PreSyn* ps = iter.second;
1388 if (use_compress_) {
1406 "Notice: The global minimum NetCon delay is %g, so turned off the "
1407 "cvode.queue_mode\n",
1409 Printf(
" use_self_queue option. The interprocessor minimum NetCon delay is %g\n",
1433 *nsendmax = nsendmax_;
1435 *nrecv_useful = nrecv_useful_;
1441 #if NRNMPI && NRNSTAT
1443 if (max_histogram_) {
1444 max_histogram_ =
NULL;
1447 max_histogram_ = mh;
1500 #if BGP_INTERVAL == 2
1504 use_bgpdma_ = (xchng_meth & 1) == 1;
1531 use_compress_ =
false;
1532 nrn_use_localgid_ =
false;
1533 }
else if (nspike > 0) {
1536 hoc_warning(
"ParallelContext.spike_compress cannot be used with cvode active", 0);
1538 use_compress_ =
false;
1539 nrn_use_localgid_ =
false;
1542 use_compress_ =
true;
1544 nrn_use_localgid_ =
false;
1550 "Notice: gid compression did not succeed. Probably more than 255 cells on one "
1554 if (!nrn_use_localgid_) {
1576 return iter->second;
1588 return iter->second;
1593 PreSyn* ps = iter.second;
1597 (*callback)(gid,
c);
1612 size_t ntot, nin, nout, nnet, nweight;
1613 ntot = nin = nout = nnet = nweight = 0;
1616 printf(
"size Presyn=%ld NetCon=%ld Point_process=%ld Prop=%ld\n",
1623 PreSyn* ps = iter.second;
1626 int n = ps->
dil_.size();
1628 for (
auto nc: ps->
dil_) {
1637 for (
const auto& iter:
gid2in_) {
1638 PreSyn* ps = iter.second;
1641 int n = ps->
dil_.size();
1643 for (
auto nc: ps->
dil_) {
1652 ntot = (nin + nout) *
sizeof(
PreSyn) + nnet *
sizeof(
NetCon) + nweight *
sizeof(
double);
1670 PreSyn* ps = iter.second;
1672 int ith = ps->
nt_->
id;
1674 int i = gidcnt[ith];
1675 cgs[ith].output_ps[
i] = ps;
1680 cgs[ith].output_vindex[
i] = inode;
static void nrnmpi_int_allgather(int *s, int *r, int n)
static void nrnmpi_barrier()
static int nrnmpi_int_allmax(int x)
void bgp_dma_receive(NrnThread *nt)
static void bgpdma_cleanup()
void bgpdma_cleanup_presyn(PreSyn *ps)
static void bgp_dma_init()
void bgp_dma_send(PreSyn *ps, double t)
void spike_record(int, IvocVect *, IvocVect *)
Object ** gid_connect(int)
void set_gid2node(int, int)
void netpar_solve(double)
IvocVect * netpar_max_histogram(IvocVect *)
void netpar_spanning_statistics(int *, int *, int *, int *)
double netpar_mindelay(double maxdelay)
auto end() -> std::vector< double >::iterator
std::vector< double > & vec()
void replace_src(PreSyn *)
TQItem * bin_event(double tdeliver, DiscreteEvent *, NrnThread *)
void deliver_events(double til, NrnThread *)
void psl_append(PreSyn *)
TQItem * event(double tdeliver, DiscreteEvent *, NrnThread *)
virtual void savestate_write(FILE *)
virtual void pgvts_deliver(double t, NetCvode *)
virtual DiscreteEvent * savestate_save()
static DiscreteEvent * savestate_read(FILE *)
virtual void send(double, NetCvode *, NrnThread *)
virtual void savestate_restore(double deliverytime, NetCvode *)
virtual void deliver(double, NetCvode *, NrnThread *)
virtual void pr(const char *, double t, NetCvode *)
virtual void send(double sendtime, NetCvode *, NrnThread *)
PreSyn(double *src, Object *osrc, Section *ssrc=nil)
void record(IvocVect *, IvocVect *idvec=nil, int rec_id=0)
VEC * cgs(MTX_FN A, void *A_params, VEC *b, VEC *r0, double tol, VEC *x)
sprintf(buf, " if (secondorder) {\n" " int _i;\n" " for (_i = 0; _i < %d; ++_i) {\n" " _p[_slist%d[_i]] += dt*_p[_dlist%d[_i]];\n" " }}\n", numeqn, listnum, listnum)
double chkarg(int, double low, double high)
void hoc_execerror(const char *, const char *)
Object ** hoc_temp_objvar(Symbol *symtemp, void *v)
void hoc_warning(const char *, const char *)
Symbol * hoc_lookup(const char *)
Object ** hoc_objgetarg(int)
Object ** hoc_temp_objptr(Object *)
static double map(void *v)
#define ITERATE(itm, lst)
unsigned char * spfixout_
unsigned char * spfixin_ovfl_
#define nrn_spikebuf_size
static double nrnmpi_wtime()
void nrn_partrans_clear()
static IvocVect * all_spikegidvec
int vector_capacity(IvocVect *)
short * nrn_is_artificial_
Point_process * ob2pntproc(Object *)
void nrn_gidout_iter(PFIO)
static double t_exchange_
static Gid2PreSyn gid2out_
static Symbol * netcon_sym_
static int weightcnt(NetCon *nc)
static Object * gid2obj_(int gid)
int nrnthread_all_spike_vectors_return(std::vector< double > &spiketvec, std::vector< int > &spikegidvec)
NEURON callback used from CORENEURON to transfer all spike vectors after simulation.
void ncs2nrn_integrate(double tstop)
void nrn_cleanup_presyn(PreSyn *)
static Gid2PreSyn gid2in_
double nrn_bgp_receive_time(int)
void nrn_spike_exchange_init()
static double min_interprocessor_delay_
PreSyn * nrn_gid2outputpresyn(int gid)
double * vector_vec(IvocVect *)
PreSyn * nrn_gid2presyn(int)
void nrnmpi_multisplit_clear()
std::unordered_map< int, PreSyn * > Gid2PreSyn
int * nrn_prop_param_size_
static int nrn_need_npe()
static double set_mindelay(double maxdelay)
static NetParEvent * npe_
static int gid_donot_remove
static int n_bgp_interval
void(* PFIO)(int, Object *)
static double last_maxstep_arg_
static double usable_mindelay_
void nrnmpi_gid_clear(int)
int nrnmpi_spike_compress(int nspike, bool gid_compress, int xchng_meth)
static void alloc_space()
Object * nrn_sec2cell(Section *)
void nrn_fake_fire(int gid, double firetime, int fake_out)
NetCvode * net_cvode_instance
static IvocVect * all_spiketvec
static void calc_actual_mindelay()
void nrncore_netpar_cellgroups_helper(CellGroup *cgs)
size_t nrncore_netpar_bytes()
Object * nrn_gid2obj(int)
void nrn_pending_selfqueue(double, NrnThread *)
int is_point_process(Object *)
void nrn_spike_exchange(struct NrnThread *nt)
int const size_t const size_t n
void * hoc_Erealloc(void *buf, size_t size)
void * hoc_Emalloc(size_t size)
static void nrnmusic_runtime_phase()
#define MUTCONSTRUCT(mkmut)
static philox4x32_key_t k
check_obj_type(o, "SectionList")
Represent main neuron object computed by single thread.
HocStruct cTemplate * ctemplate