1 #include <../../nrnconf.h> 11 #if defined(HAVE_STDINT_H) 17 #include <unordered_map> 23 extern void sgid_alltoallv(
sgid_t*
s,
int* scnt,
int* sdispl,
sgid_t* r,
int* rcnt,
int* rdispl)
27 nrnmpi_long_alltoallv_sparse(s, scnt, sdispl, r, rcnt, rdispl);
29 nrnmpi_long_alltoallv(s, scnt, sdispl, r, rcnt, rdispl);
33 #else // not NRNLONGSGID 35 extern void sgid_alltoallv(
sgid_t* s,
int* scnt,
int* sdispl,
sgid_t* r,
int* rcnt,
int* rdispl)
39 nrnmpi_int_alltoallv_sparse(s, scnt, sdispl, r, rcnt, rdispl);
45 #endif // not NRNLONGSGID 140 extern double nrnmpi_transfer_wait_;
144 extern void sgid_alltoallv(
sgid_t*,
int*,
int*,
sgid_t*,
int*,
int*);
147 extern void nrnmpi_dbl_alltoallv_sparse(
double*,
int*,
int*,
double*,
int*,
int*);
173 #define PPList partrans_PPList 174 typedef std::vector<Point_process*>
PPList;
219 if (imped_current_type_count_) {
220 imped_current_type_count_ = 0;
231 if (pv >=
p->param && pv < (
p->param +
p->param_size)) {
232 non_vsrc_update_info_[ssid] = std::pair<int,int>(
p->type, pv -
p->param);
242 if (type ==
p->type) {
243 return p->param + ix;
262 for (
int i = 0;
i < sec->
nnode; ++
i) {
281 if (sgid2srcindex_.find(sgid) != sgid2srcindex_.end()) {
282 hoc_execerr_ext(
"source var sgid %lld already in use.", (
long long)sgid);
284 sgid2srcindex_[sgid] = visources_.size();
285 visources_.push_back(
pv2node(sgid, psv));
286 sgids_.push_back(sgid);
304 if (targets_.size()) {
305 int n = targets_.size();
306 for (
int i=0;
i <
n; ++
i) {
309 hoc_execerr_ext(
"Do not know the POINT_PROCESS target for source id %zd (Hint: insert target instance of the target ref as the first argument.",
size_t(sgid2targets_[
i]));
311 double* pd =
tar_ptr(target_pntlist_[
i], target_parray_index_[i]);
330 double x = *
getarg(iarg++);
332 hoc_execerr_ext(
"target_var sgid must be >= 0: arg %d is %g\n", iarg-1, x);
338 targets_.push_back(ptv);
339 target_pntlist_.push_back(pp);
341 sgid2targets_.push_back(sgid);
351 int isrc = poutsrc_indices_[
i];
352 Node*
nd = visources_[isrc];
353 auto it = non_vsrc_update_info_.find(sgids_[isrc]);
354 if (it != non_vsrc_update_info_.end()) {
357 poutsrc_[
i] = &(
NODEV(nd));
372 if (!transfer_thread_data_){
return; }
381 transfer_thread_data_ = 0;
382 n_transfer_thread_data_ = 0;
387 if (!source_vi_buf_){
return; }
397 n_source_vi_buf_ = 0;
403 if (visources_.empty()) {
return NULL; }
412 if (!has_ecell) {
return NULL; }
416 NonVSrcUpdateInfo::iterator it;
419 source_vi_buf_[tid].
cnt = 0;
422 for (
size_t i=0;
i < visources_.size(); ++
i) {
424 it = non_vsrc_update_info_.find(sgids_[
i]);
425 if (nd->
extnode && it == non_vsrc_update_info_.end()) {
435 svib.
val =
new double[svib.
cnt];
440 for (
size_t i=0;
i < visources_.size(); ++
i) {
442 it = non_vsrc_update_info_.find(sgids_[
i]);
443 if (nd->
extnode && it == non_vsrc_update_info_.end()) {
444 int tid = nd->
_nt->
id;
460 for (
int i = 0;
i < svib.
cnt; ++
i) {
462 (*ndvi2pd)[
nd] = svib.
val +
i;
466 int isrc = poutsrc_indices_[
i];
467 Node*
nd = visources_[isrc];
468 it = non_vsrc_update_info_.find(sgids_[isrc]);
469 if (nd->
extnode && it == non_vsrc_update_info_.end()) {
470 auto search = ndvi2pd->find(nd);
471 nrn_assert(ndvi2pd->find(nd) != ndvi2pd->end());
472 poutsrc_[
i] = search->second;
483 if (targets_.empty()) {
484 if (ndvi2pd) {
delete ndvi2pd; }
500 int sgid = sgid2targets_[
i];
502 hoc_execerr_ext(
"Do not know the POINT_PROCESS target for source id %lld\n" 503 "For multiple threads, the target pointer must reference a range variable\n" 504 "of a POINT_PROCESS. Note that even for a single thread, it is\n" 505 "fastest to supply a reference to the POINT_PROCESS as the first arg." 511 transfer_thread_data_[tid].
cnt = 0;
515 if (nrn_nthread == 1) {
516 transfer_thread_data_[0].
cnt = target_pntlist_.size();
518 for (i=0; i <
n; ++
i) {
519 assert(target_pntlist_[i]);
520 tid = ((
NrnThread*)target_pntlist_[i]->_vnt)->id;
521 ++transfer_thread_data_[tid].
cnt;
528 ttd.
tv =
new double*[ttd.
cnt];
529 ttd.
sv =
new double*[ttd.
cnt];
534 for (i=0; i <
n; ++
i) {
535 if (nrn_nthread == 1) {
538 tid = ((
NrnThread*)target_pntlist_[i]->_vnt)->id;
542 ttd.
tv[
j] = targets_[
i];
548 auto search = sgid2srcindex_.find(sid);
549 if (search != sgid2srcindex_.end()) {
551 Node*
nd = visources_[search->second];
552 auto it = non_vsrc_update_info_.find(sid);
553 if (it != non_vsrc_update_info_.end()) {
556 auto search = ndvi2pd->find(nd);
558 ttd.
sv[
j] = search->second;
563 auto search = sid2insrc_.find(sid);
564 if (search != sid2insrc_.end()) {
566 ttd.
sv[
j] = insrc_buf_ + search->second;
570 hoc_execerr_ext(
"No source_var for target_var sid = %lld\n", (
long long)sid);
573 if (ndvi2pd) {
delete ndvi2pd; }
582 if (!source_vi_buf_) {
return; }
584 for (
int i = 0;
i < svb.
cnt; ++
i) {
593 if (nrn_node_ptr_change_cnt_ > vptr_change_cnt_) {
596 for (i=0; i <
n; ++
i) {
597 outsrc_buf_[
i] = *poutsrc_[
i];
604 nrnmpi_dbl_alltoallv_sparse(outsrc_buf_, outsrccnt_, outsrcdspl_,
605 insrc_buf_, insrccnt_, insrcdspl_);
610 insrc_buf_, insrccnt_, insrcdspl_);
621 hoc_execerror(
"ParallelContext.setup_transfer()",
"needs to be called.");
623 if (targets_.empty()) {
645 if (target_ptr_need_update_cnt_ > target_ptr_update_cnt_) {
649 for (
int i = 0;
i < ttd.
cnt; ++
i) {
650 *(ttd.
tv[
i]) = *(ttd.
sv[
i]);
668 #define HAVEWANT_t sgid_t 669 #define HAVEWANT_alltoallv sgid_alltoallv 670 #define HAVEWANT2Int MapSgid2Int 678 hoc_execerror(
"To use ParallelContext.setup_transfer when nhost > 1, NEURON must be configured with --with-paranrn", 0);
688 if (insrc_buf_) {
delete []
insrc_buf_; insrc_buf_ = 0; }
689 if (outsrc_buf_) {
delete []
outsrc_buf_; outsrc_buf_ = 0; }
691 if (poutsrc_) {
delete []
poutsrc_ ; poutsrc_ = 0; }
692 if (poutsrc_indices_) {
delete []
poutsrc_indices_ ; poutsrc_indices_ = 0; }
696 if (max_targets_ == 0) {
740 int szalloc = targets_.size();
741 szalloc = szalloc ? szalloc : 1;
745 sid2insrc_.reserve(szalloc);
747 for (
size_t i = 0;
i < sgid2targets_.size(); ++
i) {
749 auto search = sid2insrc_.find(sid);
750 if (search == sid2insrc_.end()) {
752 needsrc[needsrc_cnt++] = sid;
760 for (
size_t i=0;
i < sgids_.size(); ++
i) {
761 ownsrc[
i] = sgids_[
i];
766 int *send_to_want_cnt, *send_to_want_displ;
768 int *recv_from_have_cnt, *recv_from_have_displ;
770 have_to_want(ownsrc, sgids_.size(), needsrc, needsrc_cnt,
771 send_to_want, send_to_want_cnt, send_to_want_displ,
772 recv_from_have, recv_from_have_cnt, recv_from_have_displ,
776 int n = send_to_want_displ[
nhost];
777 #if 0 // done in passing in step 3 below 778 for (
int i=0;
i <
n; ++
i) {
780 nrn_assert(sgid2srcindex_.find(sgid) != sgid2srcindex_.end());
785 n = recv_from_have_displ[
nhost];
786 for (
int i=0;
i <
n; ++
i) {
787 sgid_t sgid = recv_from_have[
i];
788 nrn_assert(sid2insrc_.find(sgid) != sid2insrc_.end());
789 sid2insrc_[sgid] =
i;
795 delete [] recv_from_have;
801 outsrccnt_ = send_to_want_cnt;
802 outsrcdspl_ = send_to_want_displ;
805 outsrc_buf_ =
new double[szalloc];
806 poutsrc_ =
new double*[szalloc];
807 poutsrc_indices_ =
new int[szalloc];
810 auto search = sgid2srcindex_.find(sid);
812 Node*
nd = visources_[search->second];
813 NonVSrcUpdateInfo::iterator it;
814 it = non_vsrc_update_info_.find(sid);
815 if (it != non_vsrc_update_info_.end()) {
817 }
else if (!nd->extnode) {
818 poutsrc_[
i] = &(
NODEV(nd));
822 poutsrc_indices_[
i] = search->second;
823 outsrc_buf_[
i] = double(sid);
825 delete [] send_to_want;
829 insrccnt_ = recv_from_have_cnt;
830 insrcdspl_ = recv_from_have_displ;
833 insrc_buf_ =
new double[szalloc];
840 if (!v_structure_change) {
849 sgid2srcindex_.clear();
851 visources_.resize(0);
852 sgid2targets_.resize(0);
853 target_pntlist_.resize(0);
854 target_parray_index_.resize(0);
864 non_vsrc_update_info_.clear();
878 if (imped_change_cnt != structure_change_cnt) {
882 if (imped_current_type_count_ == 0 && targets_.size() > 0) {
883 for (
size_t i=0;
i < targets_.size(); ++
i) {
886 hoc_execerror(
"For impedance, pc.target_var requires that its first arg be a reference to the POINT_PROCESS", 0);
889 if (imped_current_type_count_ == 0) {
890 imped_current_type_count_ = 1;
891 imped_current_type_ =
new int[5];
893 imped_current_type_[0] =
type;
897 if (type == imped_current_type_[
k]) {
903 assert(imped_current_type_count_ < 5);
905 imped_current_type_count_ += 1;
911 if (imped_current_type_[
k] == tml->index) {
912 imped_current_ml_[
k] = tml->ml;
921 if (ninst != targets_.size()) {
922 hoc_execerr_ext(
"number of gap junctions, %zd, not equal to number of pc.transfer_var, %zd", ninst, targets_.size());
926 if (target_ptr_need_update_cnt_ > target_ptr_update_cnt_) {
931 if (visources_.size()) {vgap1 =
new double[visources_.size()];}
932 if (ttd && ttd->
cnt) {vgap2 =
new double[ttd->
cnt];}
933 for (
size_t i=0;
i < visources_.size(); ++
i) {
934 vgap1[
i] =
NODEV(visources_[
i]);
936 if (ttd)
for (
int i=0;
i < ttd->
cnt; ++
i) {
937 vgap2[
i] = *(ttd->
tv[
i]);
940 for (
size_t i=0;
i < visources_.size(); ++
i) {
941 NODEV(visources_[
i]) = vgap1[
i];
943 if (ttd)
for (
int i=0;
i < ttd->
cnt; ++
i) {
944 *(ttd->
tv[
i]) = vgap2[
i];
946 if (vgap1) {
delete []
vgap1; vgap1 =
NULL; }
947 if (vgap2) {
delete []
vgap2; vgap2 =
NULL; }
960 for (
size_t i=0;
i < visources_.size(); ++
i) {
968 for (
size_t i=0;
i < visources_.size(); ++
i) {
973 for (
int i=0;
i < _nt->
end; ++
i) {
978 int type = imped_current_type_[
k];
987 for (
int i=0;
i < _nt->
end; ++
i) {
1032 int ngroup,
int cn_nthread,
size_t cn_sidt_sz)
1041 if (gi ==
nullptr) {
return 0; }
1047 if (
g.src_sid.empty() &&
g.tar_sid.empty()) {
1052 sprintf(fname,
"%s/%d_gap.dat", path, group_ids[tid]);
1053 FILE* f =
fopen(fname,
"wb");
1055 fprintf(f,
"%s\n", bbcore_write_version);
1058 int ntar =
int(
g.tar_sid.size());
1059 int nsrc =
int(
g.src_sid.size());
1060 fprintf(f,
"%d ntar\n", ntar);
1061 fprintf(f,
"%d nsrc\n", nsrc);
1064 #define CHKPNT fprintf(f, "chkpnt %d\n", chkpnt++); 1066 if (!
g.src_sid.empty()) {
1068 CHKPNT fwrite(
g.src_type.data(), nsrc,
sizeof(
int), f);
1069 CHKPNT fwrite(
g.src_index.data(), nsrc,
sizeof(
int), f);
1072 if (!
g.tar_sid.empty()) {
1074 CHKPNT fwrite(
g.tar_type.data(), ntar,
sizeof(
int), f);
1075 CHKPNT fwrite(
g.tar_index.data(), ntar,
sizeof(
int), f);
1088 assert(target_pntlist_.size() == targets_.size());
1094 if (targets_.size()) {
1095 for (
size_t i=0;
i < targets_.size(); ++
i) {
1096 sgid_t sid = sgid2targets_[
i];
1099 int tid = nt ? nt->
id : 0;
1102 int ix = targets_[
i] - ml.
data[0];
1105 g.tar_sid.push_back(sid);
1106 g.tar_type.push_back(type);
1107 g.tar_index.push_back(ix);
1112 if (visources_.size()) {
1113 for (
size_t i=0;
i < sgids_.size(); ++
i) {
1116 int tid = nd->
_nt ? nd->
_nt->
id : 0;
1119 NonVSrcUpdateInfo::iterator it = non_vsrc_update_info_.find(sid);
1120 if (it != non_vsrc_update_info_.end()) {
1121 type = it->second.first;
1122 ix = it->second.second;
1128 ix = d - ml.
data[0];
1136 g.src_sid.push_back(sid);
1137 g.src_type.push_back(type);
1138 g.src_index.push_back(ix);
static int nrnmpi_int_allmax(int x)
static double * insrc_buf_
static int n_source_vi_buf_
std::vector< double * > DblPList
static double * tar_ptr(Point_process *pp, int index)
static void delete_imped_info()
struct NrnThreadMembList * next
char * hoc_object_name(Object *ob)
Represent main neuron object computed by single thread.
double * nrn_recalc_ptr(double *)
static Node * pv2node(sgid_t ssid, double *pv)
void pargap_jacobi_rhs(double *b, double *x)
static int vptr_change_cnt_
void nrn_partrans_update_ptrs()
static double nhost(void *v)
static int default_rendezvous(HAVEWANT_t key)
static Memb_list ** imped_current_ml_
static philox4x32_key_t k
sprintf(buf," if (secondorder) {\ " int _i;\" " for(_i=0;_i< %d;++_i) {\" " _p[_slist%d[_i]]+=dt *_p[_dlist%d[_i]];\" " }}\", numeqn, listnum, listnum)
std::unordered_map< Node *, double * > MapNode2PDbl
std::vector< sgid_t > SgidList
static void thread_vi_compute(NrnThread *)
static MapNode2PDbl * mk_svibuf()
double * hoc_pgetarg(int narg)
void nrnmpi_setup_transfer()
static void have_to_want(HAVEWANT_t *have, int have_size, HAVEWANT_t *want, int want_size, HAVEWANT_t *&send_to_want, int *&send_to_want_cnt, int *&send_to_want_displ, HAVEWANT_t *&recv_from_have, int *&recv_from_have_cnt, int *&recv_from_have_displ, int(*rendezvous_rank)(HAVEWANT_t))
void hoc_execerr_ext(const char *fmt,...)
printf style specification of hoc_execerror message.
std::unordered_map< sgid_t, int > MapSgid2Int
SetupTransferInfo * nrn_get_partrans_setup_info(int ngroup, int cn_nthread, size_t cn_sidt_sz)
int const size_t const size_t n
void nrn_partrans_clear()
static bool non_vsrc_setinfo(sgid_t ssid, Node *nd, double *pv)
static void nrnmpi_barrier()
const char * secname(Section *sec)
static void thread_transfer(NrnThread *)
static const char * fname(const char *name)
static int * imped_current_type_
void hoc_execerror(const char *, const char *)
static NodePList visources_
std::vector< Node * > NodePList
static void nrnmpi_int_alltoallv(int *s, int *scnt, int *sdispl, int *r, int *rcnt, int *rdispl)
fprintf(stderr, "Don't know the location of params at %p\, pp)
std::vector< double * > DblPVec
static int outsrc_buf_size_
std::map< sgid_t, std::pair< int, int > > NonVSrcUpdateInfo
std::vector< int > IntList
static int imped_current_type_count_
static SgidList sgid2targets_
static int target_ptr_update_cnt_
static TransferThreadData * transfer_thread_data_
static int n_transfer_thread_data_
const char * bbcore_write_version
static NonVSrcUpdateInfo non_vsrc_update_info_
static double ** poutsrc_
static void nrnmpi_int_allgather(int *s, int *r, int n)
static SourceViBuf * source_vi_buf_
static SetupTransferInfo * nrncore_transfer_info(int)
void(* nrnmpi_v_transfer_)()
static PPList target_pntlist_
static MapSgid2Int sgid2srcindex_
void(* nrnthread_vi_compute_)(NrnThread *)
static void nrnmpi_dbl_alltoallv(double *s, int *scnt, int *sdispl, double *r, int *rcnt, int *rdispl)
Point_process * ob2pntproc(Object *)
void(* nrnthread_v_transfer_)(NrnThread *)
void pargap_jacobi_setup(int mode)
static double nrnmpi_wtime()
static IntList target_parray_index_
static int * poutsrc_indices_
static int target_ptr_need_update_cnt_
static double * non_vsrc_update(Node *nd, int type, int ix)
static int compute_parray_index(Point_process *pp, double *ptv)
int hoc_is_object_arg(int narg)
static void target_ptr_update()
static int insrc_buf_size_
static MapSgid2Int sid2insrc_
size_t nrnbbcore_gap_write(const char *path, int *group_ids)
static double * outsrc_buf_
Object ** hoc_objgetarg(int)
Section * chk_access(void)
static int imped_change_cnt
int nrn_node_ptr_change_cnt_
static void mpi_transfer()
void(* nrn_mk_transfer_thread_data_)()