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

Commit e44cbbe

Browse files
authored
Extend CoreNEURON gap transfer to be equivalent to NEURON / Iontransfer (#446)
* Extend CoreNEURON gap transfer to be equivalent to NEURON. - except extracellular vin sources * Fill the transfer_thread_data vectors. * Update stats for number of transfer sources * Gap callback returns SetupTransferInfo* to be deleted by CoreNEURON. * Update tests for version 1.4 file transfer. * Update GPU implementation for the same * Further updates to README
1 parent 5b079c5 commit e44cbbe

28 files changed

+398
-396
lines changed

README.md

Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -45,28 +45,40 @@ CoreNEURON is now integrated into the development version of the NEURON simulato
4545

4646
HPC systems often use a module system to select software. For example, you can load the compiler, cmake, and python dependencies using module as follows:
4747

48+
```
49+
module load intel intel-mpi python cmake
50+
```
4851

49-
```
50-
module load intel intel-mpi python cmake
51-
```
5252
Note that if you are building on Cray system with the GNU toolchain, you have to set following environment variable:
5353

54-
```bash
55-
export CRAYPE_LINK_TYPE=dynamic
56-
```
54+
```
55+
export CRAYPE_LINK_TYPE=dynamic
56+
```
5757

5858
3. Run CMake with the appropriate [options](https://github.com/neuronsimulator/nrn#build-using-cmake) and additionally enable CoreNEURON with `-DNRN_ENABLE_CORENEURON=ON` option:
5959

60-
```bash
60+
```
61+
cmake .. \
62+
-DNRN_ENABLE_CORENEURON=ON \
63+
-DNRN_ENABLE_INTERVIEWS=OFF \
64+
-DNRN_ENABLE_RX3D=OFF \
65+
-DCMAKE_INSTALL_PREFIX=$HOME/install
66+
```
67+
68+
4. If you would like to enable GPU support with OpenACC, make sure to use `-DCORENRN_ENABLE_GPU=ON` option and use the PGI/NVIDIA HPC SDK compilers with CUDA. For example,
69+
70+
```
6171
cmake .. \
6272
-DNRN_ENABLE_CORENEURON=ON \
73+
-DCORENRN_ENABLE_GPU=ON
6374
-DNRN_ENABLE_INTERVIEWS=OFF \
6475
-DNRN_ENABLE_RX3D=OFF \
6576
-DCMAKE_INSTALL_PREFIX=$HOME/install
77+
-DCMAKE_C_COMPILER=nvc \
78+
-DCMAKE_CXX_COMPILER=nvc++
6679
```
67-
If you would like to enable GPU support with OpenACC, make sure to use `-DCORENRN_ENABLE_GPU=ON` option and use the PGI/NVIDIA HPC SDK compilers with CUDA.
6880

69-
> NOTE : if the CMake command files, please make sure to delete temporary CMake cache files (`CMakeCache.txt`) before rerunning CMake.
81+
NOTE : If the CMake command fails, please make sure to delete temporary CMake cache files (`CMakeCache.txt`) before rerunning CMake.
7082

7183
4. Build and Install : once the configure step is done, you can build and install the project as:
7284

@@ -89,7 +101,7 @@ As in a typical NEURON workflow, you can use `nrnivmodl` to translate MOD files:
89101
nrnivmodl mod_directory
90102
```
91103

92-
In order to enable CoreNEURON support, you must set the `-coreneuron` flag:
104+
In order to enable CoreNEURON support, you must set the `-coreneuron` flag. Make sure to necessary modules (compilers, CUDA, MPI etc) are loaded before using nrnivmodl:
93105

94106
```
95107
nrnivmodl -coreneuron mod_directory
@@ -109,7 +121,12 @@ With CoreNEURON, existing NEURON models can be run with minimal changes. For a g
109121
from neuron import coreneuron
110122
coreneuron.enable = True
111123
```
112-
3. Use `psolve` to run simulation after initialization :
124+
3. If GPU support is enabled during build, enable GPU execution using :
125+
```
126+
coreneuron.gpu = True
127+
```
128+
129+
4. Use `psolve` to run simulation after initialization :
113130

114131
```
115132
h.stdinit()
@@ -162,8 +179,10 @@ nrn_spike_gids = nrn_spike_gids.to_python()
162179
# now run CoreNEURON
163180
from neuron import coreneuron
164181
coreneuron.enable = True
182+
165183
# for GPU support
166184
# coreneuron.gpu = True
185+
167186
coreneuron.verbose = 0
168187
h.stdinit()
169188
corenrn_all_spike_t = h.Vector()
@@ -210,11 +229,10 @@ By default, OpenMP threading is enabled. You can disable it with `-DCORENRN_ENAB
210229

211230
#### GPU enabled build is failing with inlining related errors, what to do?
212231

213-
If there are large functions / procedures in the MOD file that are not inlined by the compiler, you may need to pass additional C++ flags to PGI compiler. You can try:
232+
If there are large functions / procedures in the MOD file that are not inlined by the compiler, you may need to pass additional C++ flags to PGI compiler. You can try following CXX flags:
214233

215234
```
216-
cmake .. -DCMAKE_CXX_FLAGS="-O2 -Minline=size:1000,levels:100,totalsize:40000,maxsize:4000" \
217-
-DCORENRN_ENABLE_GPU=ON -DCMAKE_INSTALL_PREFIX=$HOME/install
235+
-DCMAKE_CXX_FLAGS="-O2 -Minline=size:1000,levels:100,totalsize:40000,maxsize:4000"
218236
```
219237

220238
For other errors, please [open an issue](https://github.com/BlueBrain/CoreNeuron/issues).
@@ -261,8 +279,8 @@ CoreNEURON has support for GPUs using the OpenACC programming model when enabled
261279

262280
```bash
263281
module purge all
264-
module load pgi/19.4 cuda/10 cmake intel-mpi # change pgi, cuda and mpi modules
265-
cmake .. -DCORENRN_ENABLE_GPU=ON -DCMAKE_INSTALL_PREFIX=$HOME/install
282+
module load nvidia-hpc-sdk/20.11 cuda/11 cmake openmpi # change pgi, cuda and mpi modules
283+
cmake .. -DCORENRN_ENABLE_GPU=ON -DCMAKE_INSTALL_PREFIX=$HOME/install -DCMAKE_C_COMPILER=nvc -DCMAKE_CXX_COMPILER=nvc++
266284
make -j && make install
267285
```
268286

@@ -278,7 +296,7 @@ You have to run GPU executable with the `--gpu` flag. Make sure to enable cell r
278296
mpirun -n 1 ./bin/nrniv-core --mpi --gpu --tstop 100 --datpath ../tests/integration/ring --cell-permute 2
279297
```
280298

281-
> Note: If your model is using Random123 random number generator, you cannot use the same executable for CPU and GPU runs. We suggest to build separate executables for CPU and GPU simulations. This will be fixed in future releases.
299+
Note: If your model is using Random123 random number generator, you cannot use the same executable for CPU and GPU runs. We suggest to install separate NEURON with CoreNEURON for CPU and GPU simulations. This will be fixed in future releases.
282300

283301

284302
##### Running tests with SLURM
@@ -339,4 +357,4 @@ You can see current [contributors here](https://github.com/BlueBrain/CoreNeuron/
339357

340358
## Funding
341359

342-
CoreNEURON is developed in a joint collaboration between the Blue Brain Project and Yale University. This work has been funded by the EPFL Blue Brain Project (funded by the Swiss ETH board), NIH grant number R01NS11613 (Yale University), the European Union Seventh Framework Program (FP7/20072013) under grant agreement n◦ 604102 (HBP) and the Eu- ropean Union’s Horizon 2020 Framework Programme for Research and Innovation under Grant Agreement n◦ 720270 (Human Brain Project SGA1) and Grant Agreement n◦ 785907 (Human Brain Project SGA2).
360+
CoreNEURON is developed in a joint collaboration between the Blue Brain Project and Yale University. This work has been funded by the EPFL Blue Brain Project (funded by the Swiss ETH board), NIH grant number R01NS11613 (Yale University), the European Union Seventh Framework Program (FP7/20072013) under grant agreement n◦ 604102 (HBP) and the European Union’s Horizon 2020 Framework Programme for Research and Innovation under Grant Agreement n◦ 720270 (Human Brain Project SGA1) and Grant Agreement n◦ 785907 (Human Brain Project SGA2).

coreneuron/apps/main1.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,9 @@ extern "C" int run_solve_core(int argc, char** argv) {
577577
Instrumentor::phase_end("simulation");
578578
Instrumentor::stop_profile();
579579

580+
// update cpu copy of NrnThread from GPU
581+
update_nrnthreads_on_host(nrn_threads, nrn_nthread);
582+
580583
// direct mode and full trajectory gathering on CoreNEURON, send back.
581584
if (corenrn_embedded) {
582585
trajectory_return();

coreneuron/io/nrn2core_direct.h

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,6 @@ extern void (*nrn2core_mkmech_info_)(std::ostream&);
1717
extern void* (*nrn2core_get_global_dbl_item_)(void*, const char*& name, int& size, double*& val);
1818
extern int (*nrn2core_get_global_int_item_)(const char* name);
1919

20-
extern void (*nrn2core_get_partrans_setup_info_)(int tid,
21-
int& ntar,
22-
int& nsrc,
23-
int& type,
24-
int& ix_vpre,
25-
int*& sid_target,
26-
int*& sid_src,
27-
int*& v_indices);
28-
2920
extern int (*nrn2core_get_dat1_)(int tid,
3021
int& n_presyn,
3122
int& n_netcon,

coreneuron/io/nrn_setup.cpp

Lines changed: 64 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -63,17 +63,11 @@ int corenrn_embedded_nthread;
6363

6464
void (*nrn2core_group_ids_)(int*);
6565

66-
void (*nrn2core_get_partrans_setup_info_)(int tid,
67-
int& ntar,
68-
int& nsrc,
69-
int& type,
70-
int& ix_vpre,
71-
int*& sid_target,
72-
int*& sid_src,
73-
int*& v_indices);
74-
75-
76-
66+
extern "C" {
67+
coreneuron::nrn_partrans::SetupTransferInfo*
68+
(*nrn2core_get_partrans_setup_info_)(int ngroup, int cn_nthread,
69+
size_t cn_sidt_size);
70+
}
7771

7872
void (*nrn2core_get_trajectory_requests_)(int tid,
7973
int& bsize,
@@ -489,22 +483,12 @@ void nrn_setup(const char* filesdat,
489483
for (int i = 0; i < nrn_nthread; ++i)
490484
nrnthreads_netcon_srcgid[i] = nullptr;
491485

492-
// gap junctions
493-
if (nrn_have_gaps) {
494-
nrn_partrans::transfer_thread_data_ = new nrn_partrans::TransferThreadData[nrn_nthread];
495-
nrn_partrans::setup_info_ = new nrn_partrans::SetupInfo[userParams.ngroup];
496-
if (!corenrn_embedded) {
497-
coreneuron::phase_wrapper<coreneuron::gap>(userParams);
498-
} else {
499-
nrn_assert(sizeof(nrn_partrans::sgid_t) == sizeof(int));
500-
for (int i = 0; i < userParams.ngroup; ++i) {
501-
nrn_partrans::SetupInfo& si = nrn_partrans::setup_info_[i];
502-
(*nrn2core_get_partrans_setup_info_)(i, si.ntar, si.nsrc, si.type, si.ix_vpre,
503-
si.sid_target, si.sid_src, si.v_indices);
504-
}
505-
}
506-
nrn_partrans::gap_mpi_setup(userParams.ngroup);
507-
}
486+
// Gap junctions used to be done first in the sense of reading files
487+
// and calling gap_mpi_setup. But during phase2, gap_thread_setup and
488+
// gap_indices_permute were called after NrnThread.data was in its final
489+
// layout and mechanism permutation was determined. This is no longer
490+
// ideal as it necessitates keeping setup_info_ in existence to the end
491+
// of phase2. So gap junction setup is deferred to after phase2.
508492

509493
nrnthreads_netcon_negsrcgid_tid.resize(nrn_nthread);
510494
if (!corenrn_embedded) {
@@ -528,6 +512,28 @@ void nrn_setup(const char* filesdat,
528512
/* nrn_multithread_job supports serial, pthread, and openmp. */
529513
coreneuron::phase_wrapper<coreneuron::phase::two>(userParams, corenrn_embedded);
530514

515+
// gap junctions
516+
// Gaps are done after phase2, in order to use layout and permutation
517+
// information via calls to stdindex2ptr.
518+
if (nrn_have_gaps) {
519+
nrn_partrans::transfer_thread_data_ = new nrn_partrans::TransferThreadData[nrn_nthread];
520+
if (!corenrn_embedded) {
521+
nrn_partrans::setup_info_ = new nrn_partrans::SetupTransferInfo[
522+
nrn_nthread];
523+
coreneuron::phase_wrapper<coreneuron::gap>(userParams);
524+
} else {
525+
nrn_partrans::setup_info_ = (*nrn2core_get_partrans_setup_info_)(
526+
userParams.ngroup, nrn_nthread, sizeof(nrn_partrans::sgid_t));
527+
}
528+
529+
nrn_multithread_job(nrn_partrans::gap_data_indices_setup);
530+
nrn_partrans::gap_mpi_setup(userParams.ngroup);
531+
532+
// Whether allocated in NEURON or here, delete here.
533+
delete [] nrn_partrans::setup_info_;
534+
nrn_partrans::setup_info_ = nullptr;
535+
}
536+
531537
if (is_mapping_needed)
532538
coreneuron::phase_wrapper<coreneuron::phase::three>(userParams);
533539

@@ -578,9 +584,9 @@ void setup_ThreadData(NrnThread& nt) {
578584
}
579585

580586
void read_phasegap(NrnThread& nt, UserParams& userParams) {
581-
nrn_partrans::SetupInfo& si = nrn_partrans::setup_info_[nt.id];
582-
si.ntar = 0;
583-
si.nsrc = 0;
587+
auto& si = nrn_partrans::setup_info_[nt.id];
588+
size_t ntar = 0;
589+
size_t nsrc = 0;
584590

585591
auto& F = userParams.file_reader[nt.id];
586592
if (F.fail()) {
@@ -590,25 +596,37 @@ void read_phasegap(NrnThread& nt, UserParams& userParams) {
590596
int chkpntsave = F.checkpoint();
591597
F.checkpoint(0);
592598

593-
si.ntar = F.read_int();
594-
si.nsrc = F.read_int();
595-
si.type = F.read_int();
596-
si.ix_vpre = F.read_int();
597-
si.sid_target = F.read_array<int>(si.ntar);
598-
si.sid_src = F.read_array<int>(si.nsrc);
599-
si.v_indices = F.read_array<int>(si.nsrc);
599+
int sidt_size = F.read_int();
600+
assert(sidt_size == int(sizeof(nrn_partrans::sgid_t)));
601+
ntar = size_t(F.read_int());
602+
nsrc = size_t(F.read_int());
603+
604+
si.src_sid.resize(nsrc);
605+
si.src_type.resize(nsrc);
606+
si.src_index.resize(nsrc);
607+
if (nsrc) {
608+
F.read_array<nrn_partrans::sgid_t>(si.src_sid.data(), nsrc);
609+
F.read_array<int>(si.src_type.data(), nsrc);
610+
F.read_array<int>(si.src_index.data(), nsrc);
611+
}
600612

601-
F.checkpoint(chkpntsave);
613+
si.tar_sid.resize(ntar);
614+
si.tar_type.resize(ntar);
615+
si.tar_index.resize(ntar);
616+
if (ntar) {
617+
F.read_array<nrn_partrans::sgid_t>(si.tar_sid.data(), ntar);
618+
F.read_array<int>(si.tar_type.data(), ntar);
619+
F.read_array<int>(si.tar_index.data(), ntar);
620+
}
602621

603622
#if DEBUG
604-
printf("%d read_phasegap tid=%d type=%d %s ix_vpre=%d nsrc=%d ntar=%d\n",
605-
nrnmpi_myid, nt.id, si.type, corenrn.get_memb_func(si.type).sym, si.ix_vpre,
606-
si.nsrc, si.ntar);
623+
printf("%d read_phasegap tid=%d nsrc=%d ntar=%d\n",
624+
nrnmpi_myid, nt.id, nsrc, ntar);
607625
for (int i=0; i < si.nsrc; ++i) {
608-
printf("sid_src %d %d\n", si.sid_src[i], si.v_indices[i]);
626+
printf("src %z %d %d\n", size_t(si.src_sid[i]), si.src_type[i], si.src_index[i]);
609627
}
610-
for (int i=0; i <si. ntar; ++i) {
611-
printf("sid_tar %d %d\n", si.sid_target[i], i);
628+
for (int i=0; i <si.ntar; ++i) {
629+
printf("tar %z %d %d\n", size_t(si.src_sid[i]), si.src_type[i], si.src_index[i]);
612630
}
613631
#endif
614632
}
@@ -855,6 +873,8 @@ void nrn_cleanup() {
855873
}
856874

857875
destroy_interleave_info();
876+
877+
nrn_partrans::gap_cleanup();
858878
}
859879

860880
void delete_trajectory_requests(NrnThread& nt) {

coreneuron/io/phase2.cpp

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
#include "coreneuron/sim/multicore.hpp"
44
#include "coreneuron/io/nrn_checkpoint.hpp"
55
#include "coreneuron/utils/nrnoc_aux.hpp"
6-
#include "coreneuron/network/partrans.hpp"
76
#include "coreneuron/permute/cellorder.hpp"
87
#include "coreneuron/permute/node_permute.h"
98
#include "coreneuron/utils/vrecitem.h"
@@ -996,10 +995,6 @@ void Phase2::populate(NrnThread& nt, const UserParams& userParams) {
996995
}
997996
}
998997

999-
if (nrn_have_gaps) {
1000-
nrn_partrans::gap_thread_setup(nt);
1001-
}
1002-
1003998
pdata_relocation(nt, memb_func);
1004999

10051000
/* if desired, apply the node permutation. This involves permuting
@@ -1053,10 +1048,6 @@ void Phase2::populate(NrnThread& nt, const UserParams& userParams) {
10531048
}
10541049
}
10551050

1056-
if (nrn_have_gaps && interleave_permute_type) {
1057-
nrn_partrans::gap_indices_permute(nt);
1058-
}
1059-
10601051
set_dependencies(nt, memb_func);
10611052

10621053
fill_before_after_lists(nt, memb_func);

0 commit comments

Comments
 (0)