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);
88 extern void nrnmpi_split_clear();
96 #include "../nrnmpi/mpispike.h" 98 void nrn_timeout(
int);
102 void nrn2ncs_outputevent(
int netcon_output_index,
double firetime);
103 bool nrn_use_compress_;
104 #define use_compress_ nrn_use_compress_ 107 extern int ncs_bgp_sending_info(
int ** );
108 extern int ncs_bgp_target_hosts(
int,
int** );
109 extern int ncs_bgp_target_info(
int ** );
110 extern int ncs_bgp_mindelays(
int **,
double ** );
113 int ncs_netcon_mindelays(
int**hosts,
double **delays )
115 return ncs_bgp_mindelays(hosts, delays);
118 double ncs_netcon_localmindelay(
int srcgid )
125 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 )
144 const auto& iter =
map.find(srcgid);
145 PreSyn* ps{iter !=
map.end() ? iter->second :
nullptr};
151 NetCon* d = ps->dil_.item(netconIndex);
162 int ncs_gid_receiving_info(
int **presyngids ) {
163 return ncs_bgp_target_info( presyngids );
167 int ncs_gid_sending_count(
int **sendlist2build ) {
168 return ncs_bgp_sending_info( sendlist2build );
171 int ncs_target_hosts(
int gid,
int** targetnodes ) {
172 return ncs_bgp_target_hosts( gid, targetnodes );
178 bool nrn_use_localgid_;
179 void nrn_outputevent(
unsigned char localgid,
double firetime);
180 static std::vector<std::unique_ptr<Gid2PreSyn>> localmaps_;
183 static int nsend_, nsendmax_, nrecv_, nrecv_useful_;
188 static int ocapacity_;
192 static int spfixout_capacity_;
194 static void nrn_spike_exchange_compressed(
NrnThread*);
320 inline static void sppk(
unsigned char*
c,
int gid) {
326 inline static int spupk(
unsigned char*
c) {
335 void nrn_outputevent(
unsigned char localgid,
double firetime) {
341 if (idxout_ >= spfixout_capacity_) {
342 spfixout_capacity_ *= 2;
352 void nrn2ncs_outputevent(
int gid,
double firetime) {
359 if (idxout_ >= spfixout_capacity_) {
360 spfixout_capacity_ *= 2;
370 #if nrn_spikebuf_size == 0 372 if (i >= ocapacity_) {
383 if (i >= ocapacity_) {
390 spbufout_->gid[
i] = gid;
391 spbufout_->spiketime[
i] = firetime;
425 #if BGPDMA && (BGP_INTERVAL == 2) 461 hoc_execerror(
"usable mindelay is 0",
"(or less than dt for fixed step method)");
484 if (npe_) {
delete []
npe_; }
502 #if nrn_spikebuf_size > 0 504 spbufout_->nspike = 0;
509 nsend_ = nsendmax_ = nrecv_ = nrecv_useful_ = 0;
511 if (nrn_nthread > 0) {
535 if (use_compress_) { nrn_spike_exchange_compressed(nt);
return; }
547 #if nrn_spikebuf_size > 0 548 spbufout_->nspike =
nout_;
555 n = nrnmpi_spike_exchange();
561 tbuf_[itbuf_++] = (
unsigned long)n;
571 if (max_histogram_) {
vector_vec(max_histogram_)[0] += 1.; }
578 if (max_histogram_) {
582 #if nrn_spikebuf_size == 0 587 if (mx < spbufin_[i].nspike) {
588 mx = spbufin_[
i].nspike;
594 mx = (mx <
ms) ? mx : ms;
598 #if nrn_spikebuf_size > 0 601 int nn = spbufin_[
i].nspike;
603 for (j=0; j < nn; ++
j) {
604 auto iter =
gid2in_.find(spbufin_[i].gid[j]);
606 PreSyn* ps = iter->second;
607 ps->
send(spbufin_[i].spiketime[j], net_cvode_instance, nt);
615 #endif // nrn_spikebuf_size > 0 616 for (i = 0; i <
n; ++
i) {
619 PreSyn* ps = iter->second;
620 ps->
send(
spikein_[i].spiketime, net_cvode_instance, nt);
630 void nrn_spike_exchange_compressed(
NrnThread* nt) {
653 n = nrnmpi_spike_exchange_compressed();
659 tbuf_[itbuf_++] = (
unsigned long)n;
669 if (max_histogram_) {
vector_vec(max_histogram_)[0] += 1.; }
677 if (max_histogram_) {
687 mx = (mx <
ms) ? mx : ms;
691 if (nrn_use_localgid_) {
710 for (j=0; j < nnn; ++
j) {
715 auto iter = gps->find(lgid);
716 if (iter != gps->end()) {
717 PreSyn* ps = iter->second;
718 ps->
send(firetime + 1
e-10, net_cvode_instance, nt);
724 for ( ; j < nn; ++
j) {
728 auto iter = gps->find(lgid);
729 if (iter != gps->end()) {
730 PreSyn* ps = iter->second;
731 ps->
send(firetime+1
e-10, net_cvode_instance, nt);
745 for (j=0; j < nn; ++
j) {
752 PreSyn* ps = iter->second;
753 ps->
send(firetime+1
e-10, net_cvode_instance, nt);
762 for (i = 0; i <
n; ++
i) {
768 PreSyn* ps = iter->second;
769 ps->
send(firetime+1
e-10, net_cvode_instance, nt);
781 static void mk_localgid_rep() {
797 nrn_use_localgid_ =
true;
801 int* sbuf =
new int[ngidmax + 1];
807 for (
const auto& iter: gid2out_) {
810 ps->localgid_ = (
unsigned char)ngid;
834 sbuf = rbuf +
i*(ngidmax + 1);
836 for (
int k=0;
k < ngid; ++
k) {
837 auto iter =
gid2in_.find(
int(sbuf[
k]));
839 PreSyn* ps = iter->second;
840 (*localmaps_[
i])[k] = ps;
874 ps->send(spiketime, net_cvode_instance,
nrn_threads);
879 }
else if (fake_out && !ps) {
884 ps->send(spiketime, net_cvode_instance,
nrn_threads);
901 #if nrn_spikebuf_size > 0 919 sprintf(m,
"gid=%d already exists as an input port", gid);
920 hoc_execerror(m,
"Setup all the output ports on this process before using them as input ports.");
923 sprintf(m,
"gid=%d already exists on this process as an output port", gid);
936 if (gid_donot_remove) {
951 if (arg == 0 || arg == 3 || arg == 4) {
954 nrnmpi_split_clear();
958 if (arg == 2 || arg == 3) {
return; }
959 gid_donot_remove = 1;
971 if (ps->
dil_.empty()) {
977 for (
const auto& iter:
gid2in_) {
987 if (ps->
dil_.empty()) {
992 gid_donot_remove = 0;
1001 PreSyn* ps = iter->second;
1017 hoc_execerror(
"gid not associated with spike generation location", 0);
1019 PreSyn* ps = iter->second;
1031 sprintf(buf,
"gid=%d is in the input list. Must register prior to connecting", gid);
1040 if (!ob || ob->ctemplate != netcon_sym_->
u.
ctemplate) {
1049 ps->output_index_ = -2;
1051 ps->output_index_ = gid;
1058 PreSyn* ps = iter->second;
1060 ps->output_index_ = gid;
1066 all_spiketvec =
NULL, all_spikegidvec =
NULL;
1070 PreSyn* ps = iter->second;
1072 ps->record(spikevec, gidvec, gid);
1074 all_spiketvec = spikevec, all_spikegidvec = gidvec;
1076 PreSyn* ps = iter.second;
1087 all_spiketvec =
nullptr;
1088 all_spikegidvec =
nullptr;
1090 for (
int i = 0;
i < sz; ++
i) {
1091 int gid =
int(pd[
i]);
1094 PreSyn* ps = iter->second;
1096 ps->record(spikevec, gidvec, gid);
1105 PreSyn* ps = iter->second;
1108 cell = ps->ssrc_ ?
nrn_sec2cell(ps->ssrc_) : ps->osrc_;
1122 PreSyn* ps = iter->second;
1150 auto iter_out =
gid2out_.find(gid);
1153 ps = iter_out->second;
1160 auto iter_in =
gid2in_.find(gid);
1161 if (iter_in !=
gid2in_.end()) {
1163 ps = iter_in->second;
1177 if (!*po || (*po)->ctemplate != netcon_sym_->
u.
ctemplate) {
1180 nc = (
NetCon*)((*po)->u.this_pointer);
1182 hoc_execerror(
"target is different from 3rd arg NetCon target", 0);
1186 nc =
new NetCon(ps, target);
1207 if (v_structure_change) {
1225 hoc_execerror(
"mindelay is 0",
"(or less than dt for fixed step method)");
1233 nrn_timeout(timeout_);
1242 impl_->integ_time_ -= (npe_ ? (npe_[0].
wx_ + npe_[0].
ws_) : 0.);
1245 #if BGP_INTERVAL == 2 1259 impl_->wait_time_ += wt_;
1260 impl_->send_time_ += wt1_;
1262 impl_->wait_time_ += npe_[0].
wx_;
1263 impl_->send_time_ += npe_[0].
ws_;
1264 npe_[0].
wx_ = npe_[0].
ws_ = 0.;
1274 assert(spiketvec.size() == spikegidvec.size());
1275 if( spiketvec.size() ) {
1284 all_spikegidvec->
buffer_size(spikegidvec.size() + all_spikegidvec->
size());
1285 all_spiketvec->
vec().insert(all_spiketvec->
end(), spiketvec.begin(), spiketvec.end());
1286 all_spikegidvec->
vec().insert(all_spikegidvec->
end(), spikegidvec.begin(), spikegidvec.end());
1289 for (
size_t i = 0;
i < spikegidvec.size(); ++
i ) {
1290 auto iter =
gid2out_.find(spikegidvec[
i]);
1292 PreSyn* ps = iter->second;
1293 ps->
record(spiketvec[i]);
1310 if (mindelay > md) {
1317 for (
const auto& iter:
gid2in_) {
1318 PreSyn* ps = iter.second;
1320 if (mindelay > md) {
1326 if (use_compress_) {
1327 if (mindelay/
dt > 255) {
1343 Printf(
"Notice: The global minimum NetCon delay is %g, so turned off the cvode.queue_mode\n", od);
1344 Printf(
" use_self_queue option. The interprocessor minimum NetCon delay is %g\n", mindelay);
1367 *nsendmax = nsendmax_;
1369 *nrecv_useful = nrecv_useful_;
1375 #if NRNMPI && NRNSTAT 1377 if (max_histogram_) {
1378 max_histogram_ =
NULL;
1381 max_histogram_ = mh;
1432 #if BGP_INTERVAL == 2 1436 use_bgpdma_ = (xchng_meth & 1) == 1;
1440 #else // BGPDMA == 0 1452 use_compress_ =
false;
1453 nrn_use_localgid_ =
false;
1454 }
else if (nspike > 0) {
1456 if (
nrnmpi_myid == 0) {
hoc_warning(
"ParallelContext.spike_compress cannot be used with cvode active", 0);}
1457 use_compress_ =
false;
1458 nrn_use_localgid_ =
false;
1461 use_compress_ =
true;
1463 nrn_use_localgid_ =
false;
1468 Printf(
"Notice: gid compression did not succeed. Probably more than 255 cells on one cpu.\n");
1471 if (!nrn_use_localgid_) {
1490 return iter->second;
1502 return iter->second;
1507 PreSyn* ps = iter.second;
1511 (*callback)(gid,
c);
1526 size_t ntot, nin, nout, nnet, nweight;
1527 ntot = nin = nout = nnet = nweight = 0;
1530 printf(
"size Presyn=%ld NetCon=%ld Point_process=%ld Prop=%ld\n",
1534 PreSyn* ps = iter.second;
1537 int n = ps->
dil_.size();
1539 for (
int i=0;
i <
n; ++
i) {
1542 if (nc->
target_) { npnt += 1; }
1547 for (
const auto& iter:
gid2in_) {
1548 PreSyn* ps = iter.second;
1551 int n = ps->
dil_.size();
1553 for (
int i=0;
i <
n; ++
i) {
1556 if (nc->
target_) { npnt += 1; }
1561 ntot = (nin + nout)*
sizeof(
PreSyn) + nnet*
sizeof(
NetCon) + nweight*
sizeof(
double);
1579 PreSyn* ps = iter.second;
1581 int ith = ps->
nt_->
id;
1582 assert(ith >= 0 && ith < nrn_nthread);
1583 int i = gidcnt[ith];
1593 #if 0 // allow real cells to NOT have a direct voltage threshold.
static int nrnmpi_int_allmax(int x)
virtual void send(double, NetCvode *, NrnThread *)
void deliver_events(double til, NrnThread *)
void netpar_solve(double)
void nrnmpi_multisplit_clear()
static double min_interprocessor_delay_
void bgpdma_cleanup_presyn(PreSyn *ps)
TQItem * event(double tdeliver, DiscreteEvent *, NrnThread *)
static Gid2PreSyn gid2out_
TQItem * bin_event(double tdeliver, DiscreteEvent *, NrnThread *)
double netpar_mindelay(double maxdelay)
void nrn_gidout_iter(PFIO)
int nrnmpi_spike_compress(int nspike, bool gid_compress, int xchng_meth)
static void calc_actual_mindelay()
#define ITERATE(itm, lst)
static void bgp_dma_init()
Symbol * hoc_lookup(const char *)
Object * nrn_gid2obj(int)
virtual void savestate_write(FILE *)
virtual void send(double sendtime, NetCvode *, NrnThread *)
void ncs2nrn_integrate(double tstop)
Represent main neuron object computed by single thread.
void nrn_cleanup_presyn(PreSyn *)
void bgp_dma_receive(NrnThread *nt)
short * nrn_is_artificial_
void psl_append(PreSyn *)
check_obj_type(o, "SectionList")
auto end() -> std::vector< double >::iterator
static philox4x32_key_t k
void nrn_spike_exchange_init()
sprintf(buf," if (secondorder) {\ " int _i;\" " for(_i=0;_i< %d;++_i) {\" " _p[_slist%d[_i]]+=dt *_p[_dlist%d[_i]];\" " }}\", numeqn, listnum, listnum)
virtual void pgvts_deliver(double t, NetCvode *)
unsigned char * spfixin_ovfl_
static double set_mindelay(double maxdelay)
double nrn_bgp_receive_time(int)
static void bgpdma_cleanup()
void bgp_dma_send(PreSyn *ps, double t)
virtual void savestate_restore(double deliverytime, NetCvode *)
static double map(void *v)
virtual void deliver(double, NetCvode *, NrnThread *)
Point_process * ob2pntproc(Object *)
Object ** hoc_temp_objvar(Symbol *symtemp, void *v)
void record(IvocVect *, IvocVect *idvec=nil, int rec_id=0)
std::vector< double > & vec()
static double cell(void *v)
int const size_t const size_t n
static int gid_donot_remove
static void nrnmpi_barrier()
void nrncore_netpar_cellgroups_helper(CellGroup *cgs)
void hoc_warning(const char *, const char *)
Object ** gid_connect(int)
virtual DiscreteEvent * savestate_save()
void netpar_spanning_statistics(int *, int *, int *, int *)
void nrn_pending_selfqueue(double, NrnThread *)
static double usable_mindelay_
void hoc_execerror(const char *, const char *)
void(* PFIO)(int, Object *)
static Gid2PreSyn gid2in_
#define nrn_spikebuf_size
int is_point_process(Object *)
virtual void pr(const char *, double t, NetCvode *)
fprintf(stderr, "Don't know the location of params at %p\, pp)
void set_gid2node(int, int)
static IvocVect * all_spikegidvec
static int n_bgp_interval
int * nrn_prop_param_size_
void nrn_fake_fire(int gid, double firetime, int fake_out)
size_t nrncore_netpar_bytes()
Object * nrn_sec2cell(Section *)
PreSyn * nrn_gid2presyn(int)
void nrn_partrans_clear()
VEC * cgs(MTX_FN A, void *A_params, VEC *b, VEC *r0, double tol, VEC *x)
PreSyn(double *src, Object *osrc, Section *ssrc=nil)
#define MUTCONSTRUCT(mkmut)
static int weightcnt(NetCon *nc)
unsigned char * spfixout_
static void nrnmpi_int_allgather(int *s, int *r, int n)
static Object * gid2obj_(int gid)
void * hoc_Erealloc(void *buf, size_t size)
static DiscreteEvent * savestate_read(FILE *)
IvocVect * netpar_max_histogram(IvocVect *)
void nrn_spike_exchange(NrnThread *nt)
HocStruct cTemplate * ctemplate
void replace_src(PreSyn *)
std::unordered_map< int, PreSyn * > Gid2PreSyn
static void nrnmusic_runtime_phase()
static void alloc_space()
static int nrn_need_npe()
void spike_record(int, IvocVect *, IvocVect *)
static double nrnmpi_wtime()
int vector_capacity(IvocVect *)
PreSyn * nrn_gid2outputpresyn(int gid)
static Symbol * netcon_sym_
static IvocVect * all_spiketvec
void nrnmpi_gid_clear(int)
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.
Object ** hoc_temp_objptr(Object *)
static double last_maxstep_arg_
Object ** hoc_objgetarg(int)
static double t_exchange_
NetCvode * net_cvode_instance
double chkarg(int, double low, double high)
static NetParEvent * npe_
double * vector_vec(IvocVect *)
void * hoc_Emalloc(size_t size)