Skip to content
This repository was archived by the owner on Mar 20, 2023. It is now read-only.

Commit f2ccf7f

Browse files
authored
In memory model transfer between neuron and coreneuron (#114)
This is the first of a series of transformations to allow CoreNeuron to be embedded in NEURON and simulate the NEURON model without using data files. This change reads the bbcore_mech.dat file as an ifstream or can callback, if embedded, to get the bbcore_mech.dat file information directly from NEURON via a stringstream. In both cases the information is handled by the same mk_mech(std::istream&) function. - binary sentinel value for determining Endian consistency has been removed from bbcore_mech.dat and into a binary file called byteswap1.dat - bbcore_write_version has been bumped to 1.2 - direct transfer of globals.dat info in place - update test dataset - if OMP_NUM_THREADS is not set then it is set to nthread.
1 parent 42ae49b commit f2ccf7f

34 files changed

+660
-196
lines changed

coreneuron/nrniv/global_vars.cpp

Lines changed: 86 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@
99
#include "coreneuron/nrniv/nrniv_decl.h"
1010
#include "coreneuron/nrnoc/membfunc.h"
1111
#include "coreneuron/nrniv/nrn_assert.h"
12+
#include "coreneuron/nrniv/nrn2core_direct.h"
13+
14+
void* (*nrn2core_get_global_dbl_item_)(void*, const char*& name, int& size, double*& val);
15+
int (*nrn2core_get_global_int_item_)(const char* name);
1216

1317
using namespace std;
1418
namespace coreneuron {
@@ -37,69 +41,99 @@ void set_globals(const char* path, bool cli_global_seed, int cli_global_seed_val
3741
(*n2v)["dt"] = PSD(0, &dt);
3842
(*n2v)["t"] = PSD(0, &t);
3943

40-
string fname = string(path) + string("/globals.dat");
41-
FILE* f = fopen(fname.c_str(), "r");
42-
if (!f) {
43-
printf("ignore: could not open %s\n", fname.c_str());
44-
delete n2v;
45-
n2v = NULL;
46-
return;
47-
}
48-
49-
char line[256];
50-
char name[256];
51-
double val;
52-
int n;
53-
54-
fscanf(f, "%s\n", line);
55-
check_bbcore_write_version(line);
44+
if (corenrn_embedded) { // CoreNEURON embedded, get info direct from NEURON
5645

57-
for (;;) {
58-
nrn_assert(fgets(line, 256, f) != NULL);
59-
N2V::iterator it;
60-
if (sscanf(line, "%s %lf", name, &val) == 2) {
61-
if (strcmp(name, "0") == 0) {
62-
break;
63-
}
46+
const char* name;
47+
int size;
48+
double* val = NULL;
49+
for (void* p = NULL; (p = (*nrn2core_get_global_dbl_item_)(p, name, size, val)) != NULL;) {
50+
N2V::iterator it;
6451
it = n2v->find(name);
6552
if (it != n2v->end()) {
66-
nrn_assert(it->second.first == 0);
67-
*(it->second.second) = val;
68-
}
69-
} else if (sscanf(line, "%[^[][%d]\n", name, &n) == 2) {
70-
if (strcmp(name, "0") == 0) {
71-
break;
53+
if (size == 0) {
54+
nrn_assert(it->second.first == 0);
55+
*(it->second.second) = val[0];
56+
} else {
57+
nrn_assert(it->second.first == (size_t)size);
58+
double* pval = it->second.second;
59+
for (int i = 0; i < size; ++i) {
60+
pval[i] = val[i];
61+
}
62+
}
7263
}
73-
it = n2v->find(name);
74-
if (it != n2v->end()) {
75-
nrn_assert(it->second.first == (size_t)n);
76-
double* pval = it->second.second;
77-
for (int i = 0; i < n; ++i) {
78-
nrn_assert(fgets(line, 256, f) != NULL);
79-
nrn_assert(sscanf(line, "%lf\n", &val) == 1);
80-
pval[i] = val;
64+
delete[] val;
65+
}
66+
secondorder = (*nrn2core_get_global_int_item_)("secondorder");
67+
nrnran123_set_globalindex((*nrn2core_get_global_int_item_)("Random123_global_index"));
68+
69+
} else { // get the info from the globals.dat file
70+
71+
string fname = string(path) + string("/globals.dat");
72+
FILE* f = fopen(fname.c_str(), "r");
73+
if (!f) {
74+
printf("ignore: could not open %s\n", fname.c_str());
75+
delete n2v;
76+
n2v = NULL;
77+
return;
78+
}
79+
80+
char line[256];
81+
char name[256];
82+
double val;
83+
int n;
84+
85+
fscanf(f, "%s\n", line);
86+
check_bbcore_write_version(line);
87+
88+
for (;;) {
89+
nrn_assert(fgets(line, 256, f) != NULL);
90+
N2V::iterator it;
91+
if (sscanf(line, "%s %lf", name, &val) == 2) {
92+
if (strcmp(name, "0") == 0) {
93+
break;
94+
}
95+
it = n2v->find(name);
96+
if (it != n2v->end()) {
97+
nrn_assert(it->second.first == 0);
98+
*(it->second.second) = val;
8199
}
100+
} else if (sscanf(line, "%[^[][%d]\n", name, &n) == 2) {
101+
if (strcmp(name, "0") == 0) {
102+
break;
103+
}
104+
it = n2v->find(name);
105+
if (it != n2v->end()) {
106+
nrn_assert(it->second.first == (size_t)n);
107+
double* pval = it->second.second;
108+
for (int i = 0; i < n; ++i) {
109+
nrn_assert(fgets(line, 256, f) != NULL);
110+
nrn_assert(sscanf(line, "%lf\n", &val) == 1);
111+
pval[i] = val;
112+
}
113+
}
114+
} else {
115+
nrn_assert(0);
82116
}
83-
} else {
84-
nrn_assert(0);
85117
}
86-
}
87118

88-
while (fgets(line, 256, f)) {
89-
if (sscanf(line, "%s %d", name, &n) == 2) {
90-
if (strcmp(name, "secondorder") == 0) {
91-
secondorder = n;
92-
} else if ( strcmp(name, "Random123_globalindex") == 0) {
93-
nrnran123_set_globalindex((uint32_t)n);
119+
while (fgets(line, 256, f)) {
120+
if (sscanf(line, "%s %d", name, &n) == 2) {
121+
if (strcmp(name, "secondorder") == 0) {
122+
secondorder = n;
123+
} else if (strcmp(name, "Random123_globalindex") == 0) {
124+
nrnran123_set_globalindex((uint32_t)n);
125+
}
94126
}
95127
}
96-
}
97128

98-
fclose(f);
99-
// overwrite global.dat config if seed is specified on Command line
100-
if (cli_global_seed) {
101-
nrnran123_set_globalindex((uint32_t)cli_global_seed_value);
129+
fclose(f);
130+
131+
// overwrite global.dat config if seed is specified on Command line
132+
if (cli_global_seed) {
133+
nrnran123_set_globalindex((uint32_t)cli_global_seed_value);
134+
}
102135
}
136+
103137
#if 0
104138
for (N2V::iterator i = n2v->begin(); i != n2v->end(); ++i) {
105139
printf("%s %ld %p\n", i->first.c_str(), i->second.first, i->second.second);
@@ -109,4 +143,5 @@ void set_globals(const char* path, bool cli_global_seed, int cli_global_seed_val
109143
delete n2v;
110144
n2v = NULL;
111145
}
146+
112147
} // namespace coreneuron

coreneuron/nrniv/main1.cpp

Lines changed: 81 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ THE POSSIBILITY OF SUCH DAMAGE.
4141
#include "coreneuron/nrnoc/nrnoc_decl.h"
4242
#include "coreneuron/nrnmpi/nrnmpi.h"
4343
#include "coreneuron/nrniv/nrniv_decl.h"
44+
#include "coreneuron/nrniv/nrnmutdec.h"
4445
#include "coreneuron/nrniv/output_spikes.h"
4546
#include "coreneuron/nrniv/nrn_checkpoint.h"
4647
#include "coreneuron/utils/endianness.h"
@@ -54,9 +55,86 @@ THE POSSIBILITY OF SUCH DAMAGE.
5455
#include "coreneuron/nrniv/partrans.h"
5556
#include "coreneuron/nrniv/multisend.h"
5657
#include "coreneuron/utils/file_utils.h"
58+
#include "coreneuron/nrniv/nrn2core_direct.h"
5759
#include <string.h>
5860
#include <climits>
5961

62+
extern "C" {
63+
const char* corenrn_version() {
64+
return coreneuron::bbcore_write_version;
65+
}
66+
67+
/**
68+
* If "export OMP_NUM_THREADS=n" is not set then omp by default sets
69+
* the number of threads equal to the number of cores on this node.
70+
* If there are a number of mpi processes on this node as well, things
71+
* can go very slowly as there are so many more threads than cores.
72+
* Assume the NEURON users pc.nthread() is well chosen if
73+
* OMP_NUM_THREADS is not set.
74+
*/
75+
void set_openmp_threads(int nthread) {
76+
#if defined(_OPENMP)
77+
if (!getenv("OMP_NUM_THREADS")) {
78+
omp_set_num_threads(nthread);
79+
}
80+
#endif
81+
}
82+
83+
/**
84+
* Convert char* containing arguments from neuron to char* argv[] for
85+
* coreneuron command line argument parser.
86+
*/
87+
char* prepare_args(int& argc, char**& argv, int use_mpi, const char* arg) {
88+
// first construct all arguments as string
89+
std::string args(arg);
90+
args.insert(0, " coreneuron ");
91+
if (use_mpi) {
92+
args.append(" -mpi ");
93+
}
94+
95+
// we can't modify string with strtok, make copy
96+
char* first = strdup(args.c_str());
97+
const char* sep = " ";
98+
99+
// first count the no of argument
100+
char* token = strtok(first, sep);
101+
argc = 0;
102+
while (token) {
103+
token = strtok(NULL, sep);
104+
argc++;
105+
}
106+
free(first);
107+
108+
// now build char*argv
109+
argv = new char*[argc];
110+
first = strdup(args.c_str());
111+
token = strtok(first, sep);
112+
for (int i = 0; token; i++) {
113+
argv[i] = token;
114+
token = strtok(NULL, sep);
115+
}
116+
117+
// return actual data to be freed
118+
return first;
119+
}
120+
121+
int corenrn_embedded_run(int nthread, int have_gaps, int use_mpi, const char* arg) {
122+
corenrn_embedded = 1;
123+
corenrn_embedded_nthread = nthread;
124+
coreneuron::nrn_have_gaps = have_gaps;
125+
126+
set_openmp_threads(nthread);
127+
int argc = 0;
128+
char** argv;
129+
char* new_arg = prepare_args(argc, argv, use_mpi, arg);
130+
solve_core(argc, argv);
131+
free(new_arg);
132+
delete[] argv;
133+
134+
return corenrn_embedded;
135+
}
136+
}
137+
60138
#if 0
61139
#include <fenv.h>
62140
#define NRN_FEEXCEPT (FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW)
@@ -120,7 +198,8 @@ void nrn_init_and_load_data(int argc,
120198
mk_mech(nrnopt_get_str("--datpath").c_str());
121199

122200
// read the global variable names and set their values from globals.dat
123-
set_globals(nrnopt_get_str("--datpath").c_str(), nrnopt_get_flag("--seed"), nrnopt_get_int("--seed"));
201+
set_globals(nrnopt_get_str("--datpath").c_str(), nrnopt_get_flag("--seed"),
202+
nrnopt_get_int("--seed"));
124203

125204
report_mem_usage("After mk_mech");
126205

@@ -285,7 +364,6 @@ extern "C" int solve_core(int argc, char** argv) {
285364
reports_needs_finalize = configs.size();
286365
}
287366
}
288-
289367
// initializationa and loading functions moved to separate
290368
nrn_init_and_load_data(argc, argv, configs.size() > 0);
291369
std::string checkpoint_path = nrnopt_get_str("--checkpoint");
@@ -329,7 +407,7 @@ extern "C" int solve_core(int argc, char** argv) {
329407

330408
// register all reports into reportinglib
331409
double min_report_dt = INT_MAX;
332-
for (int i = 0; i < configs.size(); i++) {
410+
for (size_t i = 0; i < configs.size(); i++) {
333411
register_report(dt, tstop, delay, configs[i]);
334412
if (configs[i].report_dt < min_report_dt) {
335413
min_report_dt = configs[i].report_dt;

0 commit comments

Comments
 (0)