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

Commit baef043

Browse files
fouriauxpramodk
authored andcommitted
Support for multi-report (#74)
* Implementation of synapse report in coreneuron - Add mapping between synapses and variable names to register - Add a GID to compartment mapping - Add support for gids selection to report - Support for multiple reportEvents - Correct extra mapping to have reports binary identical compared to neurodamus reports * Few bug fixes and improvements while testing multiple reports: - DiscreteEvent now has require_checkpoint method to indicate whether event needs to be checkpointed. This helps when we have user-defined events like reportevent and we can skip. - Checkpoint state "store" wasn't working in multi-threaded multi-file scenario. This is because the static variable becomes thread specific and could't be modified by other threads. Storing now state in FileHandler. - Reportinglib was giving warnings for extra steps. This was due to floating point inconsistencies and "int" step. Change step to double similar to neurodamus. - Default cell permute to 0 (avoid troubles with reports) - Avoid std::endl which does flush internally and causing terrible i/o performance. - Tau instrumentation for selective profiling
1 parent 97e2840 commit baef043

26 files changed

+835
-462
lines changed

CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ option(ENABLE_OMP_RUNTIME_SCHEDULE "Use runtime schedule for OpenMP" OFF)
6363

6464
set(FRONTEND_C_COMPILER gcc CACHE FILEPATH "C compiler for building mod2c [frontend executable]")
6565
set(FRONTEND_CXX_COMPILER g++ CACHE FILEPATH "C++ compiler for building mod2c [frontend executable]")
66-
6766
## mech / mod options
6867
set(ADDITIONAL_MECHPATH "" CACHE PATH "Search path for optional additional mechanism MOD files")
6968
set(ADDITIONAL_MECHS "" CACHE FILEPATH "File containing list of additional mechanism MOD files")

coreneuron/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ include_directories(utils/randoms)
2929
include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
3030
include_directories(${MPI_INCLUDE_PATH})
3131

32-
FILE(GLOB_RECURSE coreneuron_all_headers "*.h")
32+
FILE(GLOB_RECURSE coreneuron_all_headers "*.h*")
3333
FILE(GLOB_RECURSE coreneuron_all_templates "*.ipp")
3434
FILE(GLOB_RECURSE coreneuron_all_c_files "*.c*")
3535
file(GLOB_RECURSE coreneuron_cuda_files "*.cu")

coreneuron/nrniv/main1.cpp

Lines changed: 59 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ THE POSSIBILITY OF SUCH DAMAGE.
3232
* @brief File containing main driver routine for CoreNeuron
3333
*/
3434

35+
#include <vector>
36+
#include <string.h>
3537
#include "coreneuron/utils/randoms/nrnran123.h"
3638
#include "coreneuron/nrnconf.h"
3739
#include "coreneuron/nrnoc/multicore.h"
@@ -52,6 +54,7 @@ THE POSSIBILITY OF SUCH DAMAGE.
5254
#include "coreneuron/nrniv/multisend.h"
5355
#include "coreneuron/utils/file_utils.h"
5456
#include <string.h>
57+
#include <climits>
5558

5659
#if 0
5760
#include <fenv.h>
@@ -66,6 +69,7 @@ int main1(int argc, char* argv[], char** env);
6669
void call_prcellstate_for_prcellgid(int prcellgid, int compute_gpu, int is_init);
6770
void nrn_init_and_load_data(int argc,
6871
char* argv[],
72+
bool is_mapping_needed = false,
6973
bool nrnmpi_under_nrncontrol = true,
7074
bool run_setup_cleanup = true) {
7175
#if defined(NRN_FEEXCEPT)
@@ -90,9 +94,6 @@ void nrn_init_and_load_data(int argc,
9094
// create mutex for nrn123, protect instance_count_
9195
nrnran123_mutconstruct();
9296

93-
// read command line parameters and parameter config files
94-
nrnopt_parse(argc, (const char**)argv);
95-
9697
// set global variables
9798
// precedence is: set by user, globals.dat, 34.0
9899
celsius = nrnopt_get_dbl("--celsius");
@@ -158,8 +159,8 @@ void nrn_init_and_load_data(int argc,
158159
use_interleave_permute = nrnopt_get_int("--cell-permute");
159160
cellorder_nwarp = nrnopt_get_int("--nwarp");
160161
use_solve_interleave = nrnopt_get_int("--cell-permute");
161-
#if LAYOUT==1
162-
//permuting not allowed for AoS
162+
#if LAYOUT == 1
163+
// permuting not allowed for AoS
163164
use_interleave_permute = 0;
164165
use_solve_interleave = 0;
165166
#endif
@@ -174,7 +175,7 @@ void nrn_init_and_load_data(int argc,
174175
use_phase2_ = (nrnopt_get_int("--ms-phases") == 2) ? 1 : 0;
175176

176177
// reading *.dat files and setting up the data structures, setting mindelay
177-
nrn_setup(filesdat.c_str(), nrn_need_byteswap, run_setup_cleanup);
178+
nrn_setup(filesdat.c_str(), is_mapping_needed, nrn_need_byteswap, run_setup_cleanup);
178179

179180
// Allgather spike compression and bin queuing.
180181
nrn_use_bin_queue_ = nrnopt_get_flag("--binqueue");
@@ -242,8 +243,28 @@ void call_prcellstate_for_prcellgid(int prcellgid, int compute_gpu, int is_init)
242243
int main1(int argc, char** argv, char** env) {
243244
(void)env; /* unused */
244245

246+
#if NRNMPI
247+
nrnmpi_init(1, &argc, &argv);
248+
#endif
249+
250+
// read command line parameters and parameter config files
251+
nrnopt_parse(argc, (const char**)argv);
252+
std::vector<ReportConfiguration> configs;
253+
bool reports_needs_finalize = false;
254+
255+
if (nrnopt_get_str("--report-conf").size()) {
256+
if (nrnopt_get_int("--multiple") > 1) {
257+
if (nrnmpi_myid == 0)
258+
printf("\n WARNING! : Can't enable reports with model duplications feature! \n");
259+
} else {
260+
configs = create_report_configurations(nrnopt_get_str("--report-conf").c_str(),
261+
nrnopt_get_str("--outpath").c_str());
262+
reports_needs_finalize = configs.size();
263+
}
264+
}
265+
245266
// initializationa and loading functions moved to separate
246-
nrn_init_and_load_data(argc, argv);
267+
nrn_init_and_load_data(argc, argv, configs.size() > 0);
247268
std::string checkpoint_path = nrnopt_get_str("--checkpoint");
248269
if (strlen(checkpoint_path.c_str())) {
249270
nrn_checkpoint_arg_exists = true;
@@ -264,35 +285,34 @@ int main1(int argc, char** argv, char** env) {
264285
{
265286
double v = nrnopt_get_dbl("--voltage");
266287

267-
// finitialize is not called if running in checkpoint-restore mode
288+
// TODO : if some ranks are empty then restore will go in deadlock
289+
// phase (as some ranks won't have restored anything and hence return
290+
// false in checkpoint_initialize
268291
if (!checkpoint_initialize()) {
269292
nrn_finitialize(v != 1000., v);
270293
}
271294

272295
report_mem_usage("After nrn_finitialize");
296+
double dt = nrnopt_get_dbl("--dt");
297+
double delay = nrnopt_get_dbl("--mindelay");
298+
double tstop = nrnopt_get_dbl("--tstop");
299+
300+
if (tstop < t && nrnmpi_myid == 0) {
301+
printf("Error: Stop time (%lf) < Start time (%lf), restoring from checkpoint? \n",
302+
tstop, t);
303+
abort();
304+
}
273305

274-
#ifdef ENABLE_REPORTING
275-
ReportGenerator* r = NULL;
276-
#endif
277-
278-
// if reports are enabled using ReportingLib
279-
if (nrnopt_get_flag("--report")) {
280-
#ifdef ENABLE_REPORTING
281-
if (nrnopt_get_int("--multiple") > 1) {
282-
if (nrnmpi_myid == 0)
283-
printf(
284-
"\n WARNING! : Can't enable reports with model duplications feature! \n");
285-
} else {
286-
r = new ReportGenerator(nrnopt_get_int("--report"), t, nrnopt_get_dbl("--tstop"),
287-
nrnopt_get_dbl("--dt"), nrnopt_get_dbl("--mindelay"),
288-
nrnopt_get_dbl("--dt_report"), nrnopt_get_str("--outpath"));
289-
r->register_report();
306+
// register all reports into reportinglib
307+
double min_report_dt = INT_MAX;
308+
for (int i = 0; i < configs.size(); i++) {
309+
register_report(dt, tstop, delay, configs[i]);
310+
if (configs[i].report_dt < min_report_dt) {
311+
min_report_dt = configs[i].report_dt;
290312
}
291-
#else
292-
if (nrnmpi_myid == 0)
293-
printf("\n WARNING! : Can't enable reports, recompile with ReportingLib! \n");
294-
#endif
295313
}
314+
setup_report_engine(min_report_dt, delay);
315+
configs.clear();
296316

297317
// call prcellstate for prcellgid
298318
call_prcellstate_for_prcellgid(nrnopt_get_int("--prcellgid"), compute_gpu, 0);
@@ -311,24 +331,24 @@ int main1(int argc, char** argv, char** env) {
311331
// Report global cell statistics
312332
report_cell_stats();
313333

314-
#ifdef ENABLE_SELECTIVE_PROFILING
315-
stop_profile();
316-
#endif
317-
318334
// prcellstate after end of solver
319335
call_prcellstate_for_prcellgid(nrnopt_get_int("--prcellgid"), compute_gpu, 0);
320-
321-
#ifdef ENABLE_REPORTING
322-
if (nrnopt_get_int("--report") && r)
323-
delete r;
324-
#endif
325336
}
326337

327-
write_checkpoint(nrn_threads, nrn_nthread, checkpoint_path.c_str(), nrn_need_byteswap);
328-
329338
// write spike information to outpath
330339
output_spikes(output_dir.c_str());
331340

341+
write_checkpoint(nrn_threads, nrn_nthread, checkpoint_path.c_str(), nrn_need_byteswap);
342+
343+
#ifdef ENABLE_SELECTIVE_PROFILING
344+
stop_profile();
345+
#endif
346+
347+
// must be done after checkpoint (to avoid deleting events)
348+
if (reports_needs_finalize) {
349+
finalize_report();
350+
}
351+
332352
// Cleaning the memory
333353
nrn_cleanup();
334354

coreneuron/nrniv/netcon.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,9 @@ class DiscreteEvent {
6060
virtual int type() {
6161
return DiscreteEventType;
6262
}
63-
63+
virtual bool require_checkpoint() {
64+
return true;
65+
}
6466
virtual void pr(const char*, double t, NetCvode*);
6567
};
6668

coreneuron/nrniv/node_permute.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
#ifndef node_permute_h
22
#define node_permute_h
33

4+
struct NrnThread;
5+
struct Memb_list;
6+
47
// determine ml->_permute and permute the ml->nodeindices accordingly
58
void permute_nodeindices(Memb_list* ml, int* permute);
69

coreneuron/nrniv/nrn_checkpoint.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,9 @@ class FileHandlerWrap {
7777
template <typename T>
7878
void write_array(T* p, size_t nb_elements) {
7979
// G first before chkpnt is incremented
80-
G << "chkpnt " << F.checkpoint() << std::endl;
80+
G << "chkpnt " << F.checkpoint() << "\n";
8181
for (size_t i = 0; i < nb_elements; ++i) {
82-
G << std::setprecision(8) << p[i] << std::endl;
82+
G << std::setprecision(8) << p[i] << "\n";
8383
}
8484
F.write_array(p, nb_elements); // chkpnt incremented
8585
}
@@ -176,6 +176,9 @@ void write_checkpoint(NrnThread* nt, int nb_threads, const char* dir, bool swap_
176176
if (nrnmpi_myid == 0) {
177177
write_time(output_dir);
178178
}
179+
#if NRNMPI
180+
nrnmpi_barrier();
181+
#endif
179182
}
180183

181184
static void write_phase2(NrnThread& nt, FileHandlerWrap& fh) {
@@ -595,7 +598,7 @@ static void write_phase2(NrnThread& nt, FileHandlerWrap& fh) {
595598
static void write_time(const char* output_dir) {
596599
std::ostringstream filename;
597600
FileHandler f;
598-
filename << output_dir << "/" << "time.dat";
601+
filename << output_dir << "/time.dat";
599602
f.open(filename.str().c_str(), swap_bytes, std::ios::out);
600603
f.write_array(&t, 1);
601604
f.close();
@@ -607,7 +610,7 @@ double restore_time(const char* restore_dir) {
607610
if (strlen(restore_dir)) {
608611
std::ostringstream filename;
609612
FileHandler f;
610-
filename << restore_dir << "/" << "time.dat";
613+
filename << restore_dir << "/time.dat";
611614
f.open(filename.str().c_str(), swap_bytes, std::ios::in);
612615
f.read_array(&rtime, 1);
613616
f.close();
@@ -617,9 +620,14 @@ double restore_time(const char* restore_dir) {
617620

618621
static void write_tqueue(TQItem* q, NrnThread& nt, FileHandlerWrap& fh) {
619622
DiscreteEvent* d = (DiscreteEvent*)q->data_;
623+
620624
// printf(" p %.20g %d\n", q->t_, d->type());
621625
// d->pr("", q->t_, net_cvode_instance);
622626

627+
if (!d->require_checkpoint()) {
628+
return;
629+
}
630+
623631
fh << d->type() << "\n";
624632
fh.write_array(&q->t_, 1);
625633

coreneuron/nrniv/nrn_filehandler.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ extern "C" void check_bbcore_write_version(const char*);
3434
FileHandler::FileHandler(const char* filename, bool reorder) {
3535
this->open(filename, reorder);
3636
checkpoint(0);
37+
stored_chkpnt = 0;
3738
}
3839

3940
void FileHandler::open(const char* filename, bool reorder, std::ios::openmode mode) {
@@ -50,7 +51,7 @@ void FileHandler::open(const char* filename, bool reorder, std::ios::openmode mo
5051
check_bbcore_write_version(version);
5152
}
5253
if (current_mode & std::ios::out) {
53-
F << bbcore_write_version << std::endl;
54+
F << bbcore_write_version << "\n";
5455
}
5556
}
5657

coreneuron/nrniv/nrn_filehandler.h

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ class FileHandler {
5858
bool reorder_bytes; //!< True if we need to reorder for native endiannes.
5959
std::ios_base::openmode current_mode; //!< File open mode (not stored in fstream)
6060
int chkpnt; //!< Current checkpoint number state.
61+
int stored_chkpnt; //!< last "remembered" checkpoint number state.
6162
/** Read a checkpoint line, bump our chkpnt counter, and assert equality.
6263
*
6364
* Checkpoint information is represented by a sequence "checkpt %d\n"
@@ -71,7 +72,7 @@ class FileHandler {
7172
FileHandler& operator=(const FileHandler&);
7273

7374
public:
74-
FileHandler() : reorder_bytes(false), chkpnt(0) {
75+
FileHandler() : reorder_bytes(false), chkpnt(0), stored_chkpnt(0) {
7576
}
7677

7778
explicit FileHandler(const char* filename, bool reorder = false);
@@ -97,6 +98,16 @@ class FileHandler {
9798
chkpnt = c;
9899
}
99100

101+
/** Record current chkpnt state. */
102+
void record_checkpoint() {
103+
stored_chkpnt = chkpnt;
104+
}
105+
106+
/** Restored last recorded chkpnt state. */
107+
void restore_checkpoint() {
108+
chkpnt = stored_chkpnt;
109+
}
110+
100111
/** Parse a single integer entry.
101112
*
102113
* Single integer entries are represented by their standard
@@ -265,7 +276,7 @@ class FileHandler {
265276
/* write_checkpoint is callable only for our internal uses, making it accesible to user, makes
266277
* file format unpredictable */
267278
void write_checkpoint() {
268-
F << "chkpnt " << chkpnt++ << std::endl;
279+
F << "chkpnt " << chkpnt++ << "\n";
269280
}
270281
};
271282

coreneuron/nrniv/nrn_setup.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ THE POSSIBILITY OF SUCH DAMAGE.
4747
#include "coreneuron/nrniv/nrn_checkpoint.h"
4848
#include "coreneuron/nrniv/node_permute.h"
4949
#include "coreneuron/nrniv/cellorder.h"
50-
#include "coreneuron/utils/reports/nrnreport.h"
5150
#include "coreneuron/utils/reports/nrnsection_mapping.h"
5251

5352
// file format defined in cooperation with nrncore/src/nrniv/nrnbbcore_write.cpp
@@ -559,7 +558,10 @@ void nrn_setup_cleanup() {
559558
neg_gid2out.clear();
560559
}
561560

562-
void nrn_setup(const char* filesdat, int byte_swap, bool run_setup_cleanup) {
561+
void nrn_setup(const char* filesdat,
562+
bool is_mapping_needed,
563+
int byte_swap,
564+
bool run_setup_cleanup) {
563565
/// Number of local cell groups
564566
int ngroup = 0;
565567

@@ -653,7 +655,7 @@ void nrn_setup(const char* filesdat, int byte_swap, bool run_setup_cleanup) {
653655
/* nrn_multithread_job supports serial, pthread, and openmp. */
654656
coreneuron::phase_wrapper<(coreneuron::phase)2>();
655657

656-
if (nrnopt_get_flag("--report"))
658+
if (is_mapping_needed)
657659
coreneuron::phase_wrapper<(coreneuron::phase)3>();
658660

659661
double mindelay = set_mindelay(nrnopt_get_dbl("--mindelay"));
@@ -1286,7 +1288,7 @@ void read_phase2(FileHandler& F, int imult, NrnThread& nt) {
12861288
int etype = s;
12871289
int elayout = nrn_mech_data_layout_[etype];
12881290
/* if ion is SoA, must recalculate pdata values */
1289-
/* if ion is AoS, have to deal with offset */
1291+
/* if ion is AoS, have to deal with offset */
12901292
Memb_list* eml = nt._ml_list[etype];
12911293
int edata0 = eml->data - nt._data;
12921294
int ecnt = eml->nodecount;
@@ -1760,6 +1762,9 @@ for (int i=0; i < nt.end; ++i) {
17601762
nt._vecplay[i] = new VecPlayContinuous(ml->data + ix, yvec, tvec, NULL, nt.id);
17611763
}
17621764

1765+
// store current checkpoint state to continue reading mapping
1766+
F.record_checkpoint();
1767+
17631768
// If not at end of file, then this must be a checkpoint and restore tqueue.
17641769
if (!F.eof()) {
17651770
checkpoint_restore_tqueue(nt, F);
@@ -1828,6 +1833,9 @@ for (int i=0; i < nt.end; ++i) {
18281833
void read_phase3(FileHandler& F, int imult, NrnThread& nt) {
18291834
(void)imult;
18301835

1836+
/** restore checkpoint state (before restoring queue items */
1837+
F.restore_checkpoint();
1838+
18311839
/** mapping information for all neurons in single NrnThread */
18321840
NrnThreadMappingInfo* ntmapping = new NrnThreadMappingInfo();
18331841

coreneuron/nrniv/nrn_setup.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ static void setup_ThreadData(NrnThread& nt);
5151
// Functions to load and clean data;
5252
extern void nrn_init_and_load_data(int argc,
5353
char** argv,
54+
bool is_mapping_needed = false,
5455
bool nrnmpi_under_nrncontrol = true,
5556
bool run_setup_cleanup = true);
5657
extern void nrn_setup_cleanup();

0 commit comments

Comments
 (0)