NEURON
cxprop.cpp
Go to the documentation of this file.
1 #include <../../nrnconf.h>
2 
3 /*
4 allocate and free property data and Datum arrays for nrniv
5 this allows for the possibility of
6 greater cache efficiency
7 */
8 
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <InterViews/resource.h>
12 #include <nrnmpi.h>
13 #include <nrnoc2iv.h>
14 #include <membfunc.h>
15 #include <nrnmenu.h>
16 #include <arraypool.h>
17 #include <structpool.h>
18 
19 extern void nrn_mk_prop_pools(int);
20 extern void nrn_cache_prop_realloc();
21 extern int nrn_is_ion(int);
22 extern "C" void nrn_update_ion_pointer(Symbol* sion, Datum* dp, int id, int ip);
23 void nrn_delete_prop_pool(int type);
24 #if EXTRACELLULAR
25 extern void nrn_extcell_update_param();
26 #endif
27 extern void nrn_recalc_ptrs(double* (*) (double*) );
28 static double* recalc_ptr(double*);
29 
31 
32 #define APSIZE 1000
35 
36 static int force;
37 static int npools_;
40 static void mk_prop_pools(int n);
41 
42 #define NRN_MECH_REORDER 1
43 
44 /*
45 Based on the nrn_threads tml->ml->nodelist order from the last
46 call to nrn_cache_prop_realloc() (which writes a data file) from
47 a previous launch, on this launch, read that file and create
48 pools matched to the space needed by each thread and which, from
49 the sequence of data allocation requests returns space that ends
50 up being laid out in memory in just the way we want.
51 The data file format is
52 maxtype // so we can be sure we have large enough npools_
53 nthread // number of threads
54 nmech // number of mechanisms used in this thread
55 type sz1 sz2 ntget cnt // mechanism type, double/Datum array size total number of times alloc was
56 called, how many needed for this thread
57 // the above specifies the pool allocation
58 // note that the pool chain order is the same as the thread order
59 // there are nthread of the following lists
60 cnt // number of mechanisms in thread
61 type i seq // i is the tml->ml->data[i], seq is the allocation order
62 // ie we want
63 
64 Note that the overall memory allocation sequence has to be identical
65 to the original sequence in terms of get/put for the final
66 layout to be exactly right for cache efficiency and for threads not
67 to share cache lines. However, if this is not the case, the memory allocation
68 is still correct, just not as efficient.
69 */
70 
71 #if NRN_MECH_REORDER
72 
73 static void read_temp1() {
74  // return;
75  FILE* f;
76  int nscan, maxtype, imech, nmech, type, sz1, sz2, ntget, ith, nth, i, j, cnt, seq;
77  char line[200];
78  sprintf(line, "temp_%d_%d", nrnmpi_myid, nrnmpi_numprocs);
79  f = fopen(line, "r");
80  if (!f) {
81  return;
82  }
83  force = 1;
84  nrn_assert(fgets(line, 200, f));
85  nrn_assert(sscanf(line, "%d", &maxtype) == 1);
86  mk_prop_pools(maxtype);
87  long* ntget1 = new long[maxtype];
88  for (i = 0; i < maxtype; ++i) {
89  ntget1[i] = 0;
90  }
91 
92  // allocate the pool space
93  nrn_assert(fgets(line, 200, f));
94  nrn_assert(sscanf(line, "%d", &nth) == 1);
95  for (ith = 0; ith < nth; ++ith) {
96  nrn_assert(fgets(line, 200, f));
97  nrn_assert(sscanf(line, "%d", &nmech) == 1);
98  for (imech = 0; imech < nmech; ++imech) {
99  nrn_assert(fgets(line, 200, f));
100  nrn_assert(sscanf(line, "%d %d %d %d %d", &type, &sz1, &sz2, &ntget, &cnt) == 5);
101  // printf("(%d %d %d %d %d) %s", type, sz1, sz2, ntget, cnt, line);
102  ntget1[type] = ntget;
103  if (sz1) {
104  if (!dblpools_[type]) {
105  dblpools_[type] = new DoubleArrayPool(cnt, sz1);
106  } else {
107  dblpools_[type]->grow(cnt);
108  }
109  }
110  if (sz2) {
111  if (!datumpools_[type]) {
112  datumpools_[type] = new DatumArrayPool(cnt, sz2);
113  } else {
115  }
116  }
117  }
118  }
119  for (i = 0; i < maxtype; ++i) {
120  if (dblpools_[i] && dblpools_[i]->size() < ntget1[i]) {
121  dblpools_[i]->grow(ntget1[i] - dblpools_[i]->size());
122  }
123  if (datumpools_[i] && datumpools_[i]->size() < ntget1[i]) {
124  datumpools_[i]->grow(ntget1[i] - datumpools_[i]->size());
125  }
126  }
127  delete[] ntget1;
128 
129  // now the tricky part, put items in an unnatural order
130  // first set all pointers to 0
131  for (i = 0; i < maxtype; ++i) {
132  if (dblpools_[i]) {
133  double** items = dblpools_[i]->items();
134  int sz = dblpools_[i]->size();
135  for (int j = 0; j < sz; ++j) {
136  items[j] = 0;
137  }
138  }
139  if (datumpools_[i]) {
140  Datum** items = datumpools_[i]->items();
141  int sz = datumpools_[i]->size();
142  for (int j = 0; j < sz; ++j) {
143  items[j] = 0;
144  }
145  }
146  }
147 
148  // then set the proper seq pointers
151  int* chain = new int[npools_];
152  for (i = 0; i < npools_; ++i) {
153  p1[i] = dblpools_[i];
154  p2[i] = datumpools_[i];
155  chain[i] = 0;
156  }
157  for (ith = 0; ith < nth; ++ith) {
158  nrn_assert(fgets(line, 200, f));
159  nrn_assert(sscanf(line, "%d", &cnt) == 1);
160  for (i = 0; i < cnt; ++i) {
161  nrn_assert(fgets(line, 200, f));
162  nrn_assert(sscanf(line, "%d %d %d", &type, &j, &seq));
163  if (dblpools_[type]) {
164  double** items = dblpools_[type]->items();
165  assert(items[seq] == 0);
166  items[seq] = p1[type]->element(j);
167  ++chain[type];
168  }
169  if (datumpools_[type]) {
170  Datum** items = datumpools_[type]->items();
171  assert(items[seq] == 0);
172  items[seq] = p2[type]->element(j);
173  ++chain[type];
174  }
175  }
176  for (i = 0; i < npools_; ++i) {
177  if (chain[i]) {
178  if (p1[i] && p2[i]) {
179  assert(chain[i] == (p1[i]->chain_size() + p2[i]->chain_size()));
180  } else if (p1[i]) {
181  assert(chain[i] == p1[i]->chain_size());
182  } else if (p2[i]) {
183  assert(chain[i] == p2[i]->chain_size());
184  }
185  if (p1[i]) {
186  p1[i] = p1[i]->chain();
187  }
188  if (p2[i]) {
189  p2[i] = p2[i]->chain();
190  }
191  chain[i] = 0;
192  }
193  }
194  }
195  // finally set the rest
196  for (i = 0; i < npools_; ++i) {
197  if (p1[i]) {
198  int j = 0;
199  int k = 0;
200  int n = dblpools_[i]->size();
201  int sz = p1[i]->chain_size();
202  double** items = dblpools_[i]->items();
203  for (j = 0; j < n; ++j) {
204  if (items[j] == 0) {
205  assert(k < sz);
206  items[j] = p1[i]->element(k);
207  ++k;
208  }
209  }
210  assert(k == sz);
211  }
212  if (p2[i]) {
213  int j = 0;
214  int k = 0;
215  int n = datumpools_[i]->size();
216  int sz = p2[i]->chain_size();
217  Datum** items = datumpools_[i]->items();
218  for (j = 0; j < n; ++j) {
219  if (items[j] == 0) {
220  assert(k < sz);
221  items[j] = p2[i]->element(k);
222  ++k;
223  }
224  }
225  assert(k == sz);
226  }
227  }
228  delete[] p1;
229  delete[] p2;
230  fclose(f);
231 }
232 #endif // NRN_MECH_REORDER
233 
234 static void mk_prop_pools(int n) {
235  int i;
236  if (n > npools_) {
237  DoubleArrayPool** p1 = new DoubleArrayPool*[n];
238  DatumArrayPool** p2 = new DatumArrayPool*[n];
239  for (i = 0; i < n; ++i) {
240  p1[i] = 0;
241  p2[i] = 0;
242  }
243  if (dblpools_) {
244  for (i = 0; i < npools_; ++i) {
245  p1[i] = dblpools_[i];
246  p2[i] = datumpools_[i];
247  }
248  delete[] dblpools_;
249  delete[] datumpools_;
250  }
251  dblpools_ = p1;
252  datumpools_ = p2;
253  npools_ = n;
254  }
255 }
256 
258  assert(type < npools_);
259  if (dblpools_[type]) {
260  if (dblpools_[type]->nget() > 0) {
261  hoc_execerror(memb_func[type].sym->name, "prop pool in use");
262  }
263  delete dblpools_[type];
264  dblpools_[type] = NULL;
265  }
266 }
267 
268 void nrn_mk_prop_pools(int n) {
269 #if NRN_MECH_REORDER
270  if (force == 0) {
271  read_temp1();
272  }
273 #endif
274  mk_prop_pools(n);
275 }
276 
277 extern "C" double* nrn_prop_data_alloc(int type, int count, Prop* p) {
278  if (!dblpools_[type]) {
279  dblpools_[type] = new DoubleArrayPool(APSIZE, count);
280  }
281  assert(dblpools_[type]->d2() == count);
282  p->_alloc_seq = dblpools_[type]->ntget();
283  double* pd = dblpools_[type]->alloc();
284  // if (type > 1) printf("nrn_prop_data_alloc %d %s %d %p\n", type, memb_func[type].sym->name,
285  // count, pd);
286  return pd;
287 }
288 
289 extern "C" Datum* nrn_prop_datum_alloc(int type, int count, Prop* p) {
290  int i;
291  Datum* ppd;
292  if (!datumpools_[type]) {
293  datumpools_[type] = new DatumArrayPool(APSIZE, count);
294  }
295  assert(datumpools_[type]->d2() == count);
296  p->_alloc_seq = datumpools_[type]->ntget();
297  ppd = datumpools_[type]->alloc();
298  // if (type > 1) printf("nrn_prop_datum_alloc %d %s %d %p\n", type, memb_func[type].sym->name,
299  // count, ppd);
300  for (i = 0; i < count; ++i) {
301  ppd[i]._pvoid = 0;
302  }
303  return ppd;
304 }
305 
306 extern "C" void nrn_prop_data_free(int type, double* pd) {
307  // if (type > 1) printf("nrn_prop_data_free %d %s %p\n", type, memb_func[type].sym->name, pd);
308  if (pd) {
309  dblpools_[type]->hpfree(pd);
310  }
311 }
312 
313 extern "C" void nrn_prop_datum_free(int type, Datum* ppd) {
314  // if (type > 1) printf("nrn_prop_datum_free %d %s %p\n", type, memb_func[type].sym->name, ppd);
315  if (ppd) {
316  datumpools_[type]->hpfree(ppd);
317  }
318 }
319 
321 
323 
325  if (!secpool_) {
326  secpool_ = new SectionPool(1000);
327  }
328  Section* s = secpool_->alloc();
329  return s;
330 }
332  secpool_->hpfree(s);
333 }
334 
336  if (!secpool_) {
337  return 0;
338  }
339  return secpool_->is_valid_ptr(v);
340 }
341 
344  int r = 1;
345  for (int i = 0; i < npools_; ++i) {
346  p[i] = dblpools_[i];
347  }
348  for (int it = 0; it < nrn_nthread; ++it) {
349  NrnThread* nt = nrn_threads + it;
350  for (NrnThreadMembList* tml = nt->tml; tml; tml = tml->next) {
351  Memb_list* ml = tml->ml;
352  int i = tml->index;
353  if (ml->nodecount > 0) {
354  if (!p[i]) {
355  // printf("thread %d mechanism %s pool chain does not exist\n", it,
356  // memb_func[i].sym->name);
357  r = 0;
358  continue;
359  }
360  if (p[i]->chain_size() != ml->nodecount) {
361  // printf("thread %d mechanism %s chain_size %d nodecount=%d\n", it,
362  // memb_func[i].sym->name, p[i]->chain_size(), ml->nodecount);
363  r = 0;
364  p[i] = p[i]->chain();
365  continue;
366  }
367  for (int j = 0; j < ml->nodecount; ++j) {
368  if (p[i]->element(j) != ml->data[j]) {
369  // printf("thread %d mechanism %s instance %d element %p data %p\n",
370  // it, memb_func[i].sym->name, j, p[i]->element(j), (ml->data + j));
371  r = 0;
372  }
373  }
374  p[i] = p[i]->chain();
375  }
376  }
377  }
378  delete[] p;
379  return r;
380 }
381 
382 // in-place data reallocation only intended to work when only ion data has
383 // pointers to it and no one uses pointers to other prop data. If this does
384 // not hold, then segmentation violations are likely to occur.
385 // Note that the tml list is already ordered properly so ions are first.
386 // We can therefore call the mechanism pdata_update function (which normally
387 // contains pointers to ion variables) and the ion variables will exist
388 // in their new proper locations.
389 
390 // we do one type (for all threads) at a time. Sadly, we have to keep the
391 // original pool in existence til the new pool is complete. And we have to
392 // keep old ion pools til the end.
393 
394 static DoubleArrayPool** oldpools_; // only here to allow assertion checking
395 
396 // extending to gui pointers and other well-known things that hold pointers
397 // the idea is that there are not *that* many.
398 static int recalc_index_; // the one we are working on
399 static double* recalc_ptr(double* old) {
400  // is old in the op pool?
401  for (DoubleArrayPool* op = oldpools_[recalc_index_]; op; op = op->chain()) {
402  long ds = op->chain_size() * op->d2();
403  if (old >= op->pool() && old < (op->pool() + ds)) {
404  // if so then the value gives us the pointer in the new pool
405  long offset = old - op->pool();
406  offset %= op->d2();
408  long i = (long) (*old);
409  // if (i < 0 || i >= np->size()) abort();
410  assert(i >= 0 && i < np->size());
411  double* n = np->items()[i] + offset;
412  // printf("recalc_ptr old=%p new=%p value=%g\n", old, n, *n);
413  return n;
414  }
415  }
416  return old;
417 }
418 
420 
421 static int in_place_data_realloc() {
422  int status = 0;
423  NrnThread* nt;
424  // what types are in use
425  int* types = new int[n_memb_func];
427  for (int i = 0; i < n_memb_func; ++i) {
428  types[i] = 0;
429  oldpools_[i] = dblpools_[i];
430  }
431  FOR_THREADS(nt) {
432  for (NrnThreadMembList* tml = nt->tml; tml; tml = tml->next) {
433  ++types[tml->index];
434  }
435  }
436  // iterate over those types
437  for (int i = 0; i < n_memb_func; ++i)
438  if (types[i]) {
439  int ision = nrn_is_ion(i);
440  DoubleArrayPool* oldpool = dblpools_[i];
441  DoubleArrayPool* newpool = 0;
442  // create the pool with proper chain sizes
443  int ml_total_count = 0; // so we can know if we get them all
444  FOR_THREADS(nt) {
445  for (NrnThreadMembList* tml = nt->tml; tml; tml = tml->next)
446  if (i == tml->index) {
447  ml_total_count += tml->ml->nodecount;
448  if (!newpool) {
449  newpool = new DoubleArrayPool(tml->ml->nodecount, oldpool->d2());
450  } else {
451  newpool->grow(tml->ml->nodecount);
452  }
453  break;
454  }
455  }
456  // Any extras? Put them in a new last chain.
457  // actually ml_total_count cannot be 0.
458  int extra = oldpool->nget() - ml_total_count;
459  assert(extra >= 0 && newpool);
460  if (extra) {
461  newpool->grow(extra);
462  }
463  newpool->free_all(); // items in pool data order
464  // reset ml->data pointers to the new pool and copy the values
465  FOR_THREADS(nt) {
466  for (NrnThreadMembList* tml = nt->tml; tml; tml = tml->next)
467  if (i == tml->index) {
468  Memb_list* ml = tml->ml;
469  for (int j = 0; j < ml->nodecount; ++j) {
470  double* data = ml->data[j];
471  int ntget = newpool->ntget();
472  ml->data[j] = newpool->alloc();
473  for (int k = 0; k < newpool->d2(); ++k) {
474  ml->data[j][k] = data[k];
475  }
476  // store in old location enough info
477  // to construct a pointer to the new location
478  for (int k = 0; k < newpool->d2(); ++k) {
479  data[k] = double(ntget);
480  }
481  }
482  // update any Datum pointers to ion variable locations
483  void (*s)(Datum*) = memb_func[i]._update_ion_pointers;
484  if (s)
485  for (int j = 0; j < ml->nodecount; ++j) {
486  (*s)(ml->pdata[j]);
487  }
488  }
489  }
490  // the newpool items are in the correct order for thread cache
491  // efficiency. But there may be other old items,
492  // e.g MechanismStandard that are not part of the memb lists.
493  // We made the chain item for them above. Now, sadly, we
494  // need to iterate over the MechanismStandards to find the
495  // old pool data.
496  if (extra) {
497  // should assert that newpool last chain is empty.
498  if (!mechstanlist_) {
499  Symbol* s = hoc_lookup("MechanismStandard");
501  }
502  hoc_Item* q;
503  int found = 0;
504  int looked_at = 0;
506  ++looked_at;
507  MechanismStandard* ms = (MechanismStandard*) (OBJ(q)->u.this_pointer);
508  NrnProperty* np = ms->np();
509  if (np->type() == i && np->deleteable()) {
510  Prop* p = np->prop();
511  double* data = p->param;
512  int ntget = newpool->ntget();
513  p->param = newpool->alloc();
514  for (int k = 0; k < newpool->d2(); ++k) {
515  p->param[k] = data[k];
516  }
517  // store in old location enough info
518  // to construct a pointer to the new location
519  for (int k = 0; k < newpool->d2(); ++k) {
520  data[k] = double(ntget);
521  }
522  ++found;
523  }
524  }
525  // unless we missed something that holds a prop pointer.
526  // printf("%d extra %s, looked at %d, found %d\n", extra,
527  // memb_func[i].sym->name, looked_at, found);
528  assert(extra == found);
529  }
530 
531  dblpools_[i] = newpool;
532  // let the gui and other things update
533  recalc_index_ = i;
535 
536  if (0 && !ision) {
537  delete oldpool;
538  assert(oldpool == oldpools_[i]);
539  oldpools_[i] = 0;
540  }
541  }
542  // update p->param for the node properties
543  Memb_list** mlmap = new Memb_list*[n_memb_func];
544  FOR_THREADS(nt) {
545  // make a map
546  for (int i = 0; i < n_memb_func; ++i) {
547  mlmap[i] = 0;
548  }
549  for (NrnThreadMembList* tml = nt->tml; tml; tml = tml->next) {
550  mlmap[tml->index] = tml->ml;
551  tml->ml->nodecount = 0;
552  }
553  // fill
554  for (int i = 0; i < nt->end; ++i) {
555  Node* nd = nt->_v_node[i];
556  for (Prop* p = nd->prop; p; p = p->next) {
557  if (memb_func[p->type].current || memb_func[p->type].state ||
558  memb_func[p->type].initialize) {
559  Memb_list* ml = mlmap[p->type];
560  assert(ml->nodelist[ml->nodecount] == nd);
561  if (!memb_func[p->type].hoc_mech) {
562  p->param = ml->data[ml->nodecount];
563  }
564  ++ml->nodecount;
565  }
566  }
567  }
568  }
569  // one more thing to do for extracellular
570 #if EXTRACELLULAR
572 #endif
573  // finally get rid of the old ion pools
574  for (int i = 0; i < n_memb_func; ++i)
575  if (types[i] && oldpools_[i]) {
576  delete oldpools_[i];
577  }
578  delete[] oldpools_;
579  delete[] types;
580  delete[] mlmap;
581  // if useful, we could now realloc the Datum pools and just make
582  // bit copies of the Datum values.
583  return status;
584 }
585 
586 extern "C" void nrn_update_ion_pointer(Symbol* sion, Datum* dp, int id, int ip) {
587  int iontype = sion->subtype;
590  assert(np);
591  assert(op);
592  assert(ip < op->d2());
593  assert(1); // should point into pool() for one of the op pool chains
594  // and the index should be a pointer to the double in np
595  long i = (long) (*dp[id].pval);
596  assert(i >= 0 && i < np->size());
597  double* pvar = np->items()[i];
598  dp[id].pval = pvar + ip;
599 }
600 
601 
602 void nrn_poolshrink(int shrink) {
603  if (shrink) {
604  for (int i = 0; i < npools_; ++i) {
605  auto& pdbl = dblpools_[i];
606  auto& pdatum = datumpools_[i];
607  if ((pdbl && pdbl->nget() == 0)) {
609  }
610  if (pdatum && pdatum->nget() == 0) {
611  delete datumpools_[i];
612  datumpools_[i] = NULL;
613  }
614  }
615  } else {
616  Printf("poolshrink --- type name (dbluse, size) (datumuse, size)\n");
617  for (int i = 0; i < npools_; ++i) {
618  auto& pdbl = dblpools_[i];
619  auto& pdatum = datumpools_[i];
620  if (pdbl || pdatum) {
621  Printf("%d %s (%ld, %d) (%ld, %d)\n",
622  i,
623  (memb_func[i].sym ? memb_func[i].sym->name : "noname"),
624  (pdbl ? pdbl->nget() : 0),
625  (pdbl ? pdbl->size() : 0),
626  (pdatum ? pdatum->nget() : 0),
627  (pdatum ? pdatum->size() : 0));
628  }
629  }
630  }
631 }
632 
635  // printf("begin nrn_prop_is_cache_efficient %d\n", nrn_prop_is_cache_efficient());
637  // printf("end nrn_prop_is_cache_efficient %d\n", nrn_prop_is_cache_efficient());
638  }
639  return;
640 
641 
642 #if NRN_MECH_REORDER
644  FILE* f;
645  char buf[100];
646  int i, it, type;
647  // we wish to rearrange the arrays so that they are in memb_list->data order within
648  // the ArrayPools. We do not want to use up a lot of temporary space to do this
649  // because there may not be much left.
650  // In each pool all the pointers between put and get (nget of them) are in use.
651  if (force) {
652  sprintf(buf, "temp2_%d", nrnmpi_myid);
653  } else {
654  sprintf(buf, "temp_%d_%d", nrnmpi_myid, nrnmpi_numprocs);
655  }
656  f = fopen(buf, "w");
657  fprintf(f, "%d\n", n_memb_func);
658  fprintf(f, "%d\n", nrn_nthread);
659  for (it = 0; it < nrn_nthread; ++it) {
660  NrnThread* nt = nrn_threads + it;
661  // how many mechanisms used in this thread
662  i = 0;
663  for (NrnThreadMembList* tml = nt->tml; tml; tml = tml->next) {
664  ++i;
665  }
666  fprintf(f, "%d\n", i);
667  for (NrnThreadMembList* tml = nt->tml; tml; tml = tml->next) {
668  Memb_list* ml = tml->ml;
669  i = tml->index;
670  int j, cnt = ml->nodecount;
671  int sz1 = 0, sz2 = 0, ntget = 0;
672  if (dblpools_[i]) {
673  sz1 = dblpools_[i]->d2();
674  ntget = dblpools_[i]->ntget();
675  }
676  if (datumpools_[i]) {
677  sz2 = datumpools_[i]->d2();
678  }
679  fprintf(f, "%d %d %d %d %d %s\n", i, sz1, sz2, ntget, cnt, memb_func[i].sym->name);
680  }
681  }
682  // above is enough for allocating the pools. Now the proper order info.
683  Memb_list** mlmap = new Memb_list*[n_memb_func];
684  for (it = 0; it < nrn_nthread; ++it) {
685  NrnThread* nt = nrn_threads + it;
686  for (i = 0; i < n_memb_func; ++i) {
687  mlmap[i] = 0;
688  } // unnecessary but ...
689  // how many prop used in this thread
690  int cnt = 0;
691  for (NrnThreadMembList* tml = nt->tml; tml; tml = tml->next) {
692  cnt += tml->ml->nodecount;
693  tml->ml->nodecount = 0; // recount them below
694  mlmap[tml->index] = tml->ml;
695  }
696  fprintf(f, "%d\n", cnt);
697  int cnt2 = 0;
698  for (i = 0; i < nt->end; ++i) {
699  Node* nd = nt->_v_node[i];
700  for (Prop* p = nd->prop; p; p = p->next) {
701  if (memb_func[p->type].current || memb_func[p->type].state ||
702  memb_func[p->type].initialize) {
703  Memb_list* ml = mlmap[p->type];
704  if (!ml || nd != ml->nodelist[ml->nodecount]) {
705  abort();
706  }
707  assert(ml && nd == ml->nodelist[ml->nodecount]);
708  nrn_assert(fprintf(f, "%d %d %ld\n", p->type, ml->nodecount++, p->_alloc_seq) >
709  0);
710  ++cnt2;
711  }
712  }
713  }
714  assert(cnt == cnt2);
715  }
716  delete[] mlmap;
717  fclose(f);
718 #endif
719 }
720 
721 // for avoiding interthread cache line sharing
722 // each thread needs its own pool instance
723 extern "C" void* nrn_pool_create(long count, int itemsize) {
724  CharArrayPool* p = new CharArrayPool(count, itemsize);
725  return (void*) p;
726 }
727 extern "C" void nrn_pool_delete(void* pool) {
728  CharArrayPool* p = (CharArrayPool*) pool;
729  delete p;
730 }
731 extern "C" void* nrn_pool_alloc(void* pool) {
732  CharArrayPool* p = (CharArrayPool*) pool;
733  return (void*) p->alloc();
734 }
735 extern "C" void nrn_pool_free(void* pool, void* item) {
736  CharArrayPool* p = (CharArrayPool*) pool;
737  p->hpfree(static_cast<char*>(item));
738 }
739 extern "C" void nrn_pool_freeall(void* pool) {
740  CharArrayPool* p = (CharArrayPool*) pool;
741  p->free_all();
742 }
Memb_func * memb_func
Definition: init.cpp:123
short type
Definition: cabvars.h:9
T ** items()
Definition: arraypool.h:56
long chain_size()
Definition: arraypool.h:63
long d2()
Definition: arraypool.h:50
void grow(long ninc)
Definition: arraypool.h:106
void hpfree(T *)
Definition: arraypool.h:164
T * element(long i)
Definition: arraypool.h:53
T * alloc()
Definition: arraypool.h:149
long ntget()
Definition: arraypool.h:47
void free_all()
Definition: arraypool.h:172
long nget()
Definition: arraypool.h:44
ArrayPool * chain()
Definition: arraypool.h:60
int size()
Definition: arraypool.h:31
bool deleteable()
Definition: ndatclas.cpp:107
int type() const
Definition: ndatclas.cpp:119
Prop * prop() const
Definition: ndatclas.cpp:123
T * alloc()
Definition: structpool.h:114
int is_valid_ptr(void *)
Definition: structpool.h:98
void hpfree(T *)
Definition: structpool.h:128
void nrn_cache_prop_realloc()
Definition: cxprop.cpp:633
static DoubleArrayPool ** oldpools_
Definition: cxprop.cpp:394
void nrn_pool_free(void *pool, void *item)
Definition: cxprop.cpp:735
void nrn_recalc_ptrs(double *(*)(double *))
int nrn_is_ion(int)
Definition: eion.cpp:51
Datum * nrn_prop_datum_alloc(int type, int count, Prop *p)
Definition: cxprop.cpp:289
static int npools_
Definition: cxprop.cpp:37
static int force
Definition: cxprop.cpp:36
void nrn_prop_datum_free(int type, Datum *ppd)
Definition: cxprop.cpp:313
static int in_place_data_realloc()
Definition: cxprop.cpp:421
void nrn_mk_prop_pools(int)
Definition: cxprop.cpp:268
void nrn_update_ion_pointer(Symbol *sion, Datum *dp, int id, int ip)
Definition: cxprop.cpp:586
ArrayPool< Datum > DatumArrayPool
Definition: cxprop.cpp:34
static SectionPool * secpool_
Definition: cxprop.cpp:322
void * nrn_pool_alloc(void *pool)
Definition: cxprop.cpp:731
void nrn_prop_data_free(int type, double *pd)
Definition: cxprop.cpp:306
static void mk_prop_pools(int n)
Definition: cxprop.cpp:234
static DoubleArrayPool ** dblpools_
Definition: cxprop.cpp:38
#define APSIZE
Definition: cxprop.cpp:32
static DatumArrayPool ** datumpools_
Definition: cxprop.cpp:39
void * nrn_pool_create(long count, int itemsize)
Definition: cxprop.cpp:723
static int recalc_index_
Definition: cxprop.cpp:398
static hoc_List * mechstanlist_
Definition: cxprop.cpp:419
int nrn_is_valid_section_ptr(void *v)
Definition: cxprop.cpp:335
void nrn_pool_delete(void *pool)
Definition: cxprop.cpp:727
Section * nrn_section_alloc()
Definition: cxprop.cpp:324
static double * recalc_ptr(double *)
Definition: cxprop.cpp:399
void nrn_delete_prop_pool(int type)
Definition: cxprop.cpp:257
ArrayPool< char > CharArrayPool
Definition: cxprop.cpp:30
int nrn_prop_is_cache_efficient()
Definition: cxprop.cpp:342
void nrn_pool_freeall(void *pool)
Definition: cxprop.cpp:739
void nrn_poolshrink(int shrink)
Definition: cxprop.cpp:602
static void read_temp1()
Definition: cxprop.cpp:73
void nrn_section_free(Section *s)
Definition: cxprop.cpp:331
double * nrn_prop_data_alloc(int type, int count, Prop *p)
Definition: cxprop.cpp:277
Pool< Section > SectionPool
Definition: cxprop.cpp:320
ArrayPool< double > DoubleArrayPool
Definition: cxprop.cpp:33
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)
ms
Definition: extargs.h:1
void nrn_extcell_update_param(void)
Definition: extcelln.cpp:331
void hoc_execerror(const char *, const char *)
Definition: hoc.cpp:754
char buf[512]
Definition: init.cpp:13
Symbol * hoc_lookup(const char *)
#define assert(ex)
Definition: hocassrt.h:32
#define OBJ(q)
Definition: hoclist.h:67
static char line[MAXLINE]
Definition: ivecop.c:35
void
#define pval
Definition: md1redef.h:32
#define v
Definition: md1redef.h:4
#define id
Definition: md1redef.h:33
#define i
Definition: md1redef.h:12
#define ITERATE(itm, lst)
Definition: model.h:25
#define Printf
Definition: model.h:237
int nrn_nthread
Definition: multicore.cpp:46
NrnThread * nrn_threads
Definition: multicore.cpp:47
#define FOR_THREADS(nt)
Definition: multicore.h:104
#define fprintf
Definition: mwprefix.h:30
int iontype(char *s1, char *s2)
Definition: nocpout.cpp:1885
#define nrn_assert(ex)
Definition: nrnassrt.h:53
int const size_t const size_t n
Definition: nrngsl.h:11
size_t q
return status
size_t p
size_t j
int nrnmpi_myid
int nrnmpi_numprocs
int n_memb_func
Definition: init.cpp:440
static philox4x32_key_t k
Definition: nrnran123.cpp:11
#define data
Definition: rbtqueue.cpp:49
FILE * fopen()
#define cnt
Definition: spt2queue.cpp:19
#define NULL
Definition: sptree.h:16
void * hoc_mech
Definition: membfunc.h:54
Pvmi current
Definition: membfunc.h:33
Pvmi state
Definition: membfunc.h:35
Pvmi initialize
Definition: membfunc.h:36
int nodecount
Definition: nrnoc_ml.h:18
Node ** nodelist
Definition: nrnoc_ml.h:5
double ** data
Definition: nrnoc_ml.h:14
Datum ** pdata
Definition: nrnoc_ml.h:15
Definition: section.h:133
struct Prop * prop
Definition: section.h:152
Represent main neuron object computed by single thread.
Definition: multicore.h:58
NrnThreadMembList * tml
Definition: multicore.h:62
int end
Definition: multicore.h:65
Node ** _v_node
Definition: multicore.h:77
struct NrnThreadMembList * next
Definition: multicore.h:34
Definition: section.h:214
Definition: model.h:57
long subtype
Definition: model.h:59
union Symbol::@18 u
HocStruct cTemplate * ctemplate
Definition: hocdec.h:152
hoc_List * olist
Definition: hocdec.h:204
Definition: hocdec.h:177
double * pval
Definition: hocdec.h:181
void * _pvoid
Definition: hocdec.h:187