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

Copies to NEURON the voltage, i_membrane_, and mechanism data. #382

Merged
merged 6 commits into from
Aug 26, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions coreneuron/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ if(CORENRN_ENABLE_GPU)
${CMAKE_CURRENT_SOURCE_DIR}/utils/randoms/nrnran123.cpp
${CMAKE_CURRENT_SOURCE_DIR}/io/nrn_setup.cpp
${CMAKE_CURRENT_SOURCE_DIR}/io/setup_fornetcon.cpp
${CMAKE_CURRENT_SOURCE_DIR}/io/corenrn_data_return.cpp
${CMAKE_CURRENT_SOURCE_DIR}/io/global_vars.cpp)

set_source_files_properties(${DIMPLIC_CODE_FILE} ${NMODL_INBUILT_MOD_OUTPUTS} PROPERTIES
Expand Down
3 changes: 3 additions & 0 deletions coreneuron/apps/main1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ THE POSSIBILITY OF SUCH DAMAGE.
#include "coreneuron/network/multisend.hpp"
#include "coreneuron/io/file_utils.hpp"
#include "coreneuron/io/nrn2core_direct.h"
#include "coreneuron/io/core2nrn_data_return.hpp"

extern "C" {
const char* corenrn_version() {
Expand Down Expand Up @@ -609,6 +610,8 @@ extern "C" int run_solve_core(int argc, char** argv) {
(*nrn2core_all_weights_return_)(weights);
}

core2nrn_data_return();

{
Instrumentor::phase p("checkpoint");
write_checkpoint(nrn_threads, nrn_nthread, corenrn_param.checkpointpath.c_str());
Expand Down
174 changes: 174 additions & 0 deletions coreneuron/io/core2nrn_data_return.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
/*
Copyright (c) 2020, Blue Brain Project
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "coreneuron/coreneuron.hpp"
#include "coreneuron/io/nrn2core_direct.h"
#include "coreneuron/sim/multicore.hpp"
#include "coreneuron/nrniv/nrniv_decl.h"
#include "coreneuron/io/core2nrn_data_return.hpp"

/** @brief, Information from NEURON to help with copying data to NEURON.
* Info for copying voltage, i_membrane_, and mechanism data.
* See implementaton in
* nrn/src/nrniv/nrnbbcore_write.cpp:nrnthreads_type_return.
* Return is size of either the returned data pointer or the number
* of pointers in mdata. tid is the thread index.
*/
size_t (*nrn2core_type_return_)(int type, int tid,
double*& data, double**& mdata);

namespace coreneuron {

/** @brief permuted array copied to unpermuted array
* If permute is NULL then just a copy
*/
static void inverse_permute_copy(size_t n, double* permuted_src, double* dest,
int* permute)
{
if (permute) {
for (size_t i = 0; i < n; ++i) {
dest[i] = permuted_src[permute[i]];
}
}else{
std::copy(permuted_src, permuted_src + n, dest);
}
}

/** @brief SoA permuted mechanism data copied to unpermuted AoS data.
* dest is an array of n pointers to the beginning of each sz length array.
* src is a contiguous array of sz segments of size stride. The stride
* may be slightly greater than n for purposes of alignment.
* Each of the sz segments of src are permuted.
*/
static void soa2aos_inverse_permute_copy(size_t n, int sz, int stride,
double* src, double** dest, int* permute)
{
// src is soa and permuted. dest is n pointers to sz doubles (aos).
for (size_t instance = 0; instance < n; ++instance) {
double* d = dest[instance];
double* s = src + permute[instance];
for (int i = 0; i < sz; ++i) {
d[i] = s[i*stride];
}
}
}

/** @brief SoA unpermuted mechanism data copied to unpermuted AoS data.
* dest is an array of n pointers to the beginning of each sz length array.
* src is a contiguous array of sz segments of size stride. The stride
* may be slightly greater than n for purposes of alignment.
* Each of the sz segments of src have the same order as the n pointers
* of dest.
*/
static void soa2aos_unpermuted_copy(size_t n, int sz, int stride,
double* src, double** dest)
{
// src is soa and permuted. dest is n pointers to sz doubles (aos).
for (size_t instance = 0; instance < n; ++instance) {
double* d = dest[instance];
double* s = src + instance;
for (int i = 0; i < sz; ++i) {
d[i] = s[i*stride];
}
}
}

/** @brief AoS mechanism data copied to AoS data.
* dest is an array of n pointers to the beginning of each sz length array.
* src is a contiguous array of n segments of size sz.
*/
static void aos2aos_copy(size_t n, int sz, double* src, double** dest) {
for (size_t instance = 0; instance < n; ++instance) {
double* d = dest[instance];
double* s = src + (instance*sz);
std::copy(s, s + sz, d);
}
}

/** @brief copy data back to NEURON.
* Copies t, voltage, i_membrane_ if it used, and mechanism param data.
*/
void core2nrn_data_return() {
if (!nrn2core_type_return_) {
return;
}
for (int tid = 0; tid < nrn_nthread; ++tid) {
size_t n = 0;
double* data = nullptr;
double** mdata = nullptr;
NrnThread& nt = nrn_threads[tid];

n = (*nrn2core_type_return_)(0, tid, data, mdata); // 0 means time
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

neuron doesn't have mechanism type 0 and that is the reason we are using first parameter0 to nrn2core_type_return_?

I wonder if we should change this to some different value (e.g. < 0) in case above assumption change?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change this to some different value
Good idea Should add to the enum (on both NEURON and CoreNEURON side).

if (n) { // not the empty thread
data[0] = nt._t;
}

if (nt.end) { // transfer voltage and possibly i_membrane_
n = (*nrn2core_type_return_)(voltage, tid, data, mdata);
assert(n == size_t(nt.end) && data);
inverse_permute_copy(n, nt._actual_v, data, nt._permute);

if (nt.nrn_fast_imem) {
n = (*nrn2core_type_return_)(i_membrane_, tid, data, mdata);
assert(n == size_t(nt.end) && data);
inverse_permute_copy(n, nt.nrn_fast_imem->nrn_sav_rhs, data, nt._permute);
}
}

for (NrnThreadMembList* tml = nt.tml; tml; tml = tml->next) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just a remark : we can start using auto more : for (auto& tml = nt.tml;

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would this really work here without changing NrnThreadMembList into std::vector or giving it some kind of explicit iterator operator?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

auto just deduce the type from assignment. If nt.tml becomes container like std::vector then we have to use for(auto& tml : nt.tml).

int mtype = tml->index;
Memb_list* ml = tml->ml;
n = (*nrn2core_type_return_)(mtype, tid, data, mdata);
assert(n == size_t(ml->nodecount) && mdata);
if (n == 0) {
continue;
}
// NEURON is AoS, CoreNEURON may be SoA and may be permuted.
// On the NEURON side, the data is actually contiguous because of
// cache_efficient, but that may not be the case for ARTIFICIAL_CELL.
// For initial implementation simplicity, use the mdata info which gives
// a double* for each param_size mech instance.
int* permute = ml->_permute;
double* cndat = ml->data;
int layout = corenrn.get_mech_data_layout()[mtype];
int sz = corenrn.get_prop_param_size()[mtype];
if (layout == 0) { /* SoA */
int stride = ml->_nodecount_padded;
if (permute) {
soa2aos_inverse_permute_copy(n, sz, stride, cndat, mdata, permute);
} else {
soa2aos_unpermuted_copy(n, sz, stride, cndat, mdata);
}
} else { /* AoS */
aos2aos_copy(n, sz, cndat, mdata);
}
}
}
}

} // namespace coreneuron
40 changes: 40 additions & 0 deletions coreneuron/io/core2nrn_data_return.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
Copyright (c) 2016, Blue Brain Project
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
THE POSSIBILITY OF SUCH DAMAGE.
*/

#ifndef _H_CORENRNDATARETURN_
#define _H_CORENRNDATARETURN_

namespace coreneuron {

/** @brief Copies back to NEURON the voltage, i_membrane_, and mechanism data.
*/
extern void core2nrn_data_return();

} // namespace coreneuron
#endif // _H_CORENRNDATARETURN_

3 changes: 3 additions & 0 deletions coreneuron/io/nrn2core_direct.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,9 @@ extern int (*nrn2core_all_spike_vectors_return_)(std::vector<double>& spikevec,
/* send all weights to NEURON */
extern void (*nrn2core_all_weights_return_)(std::vector<double*>& weights);

/* get data array pointer from NEURON to copy into. */
extern size_t (*nrn2core_type_return_)(int type, int tid, double*& data,
double**& mdata);
} // extern "C"

#endif /* nrn2core_direct_h */
7 changes: 5 additions & 2 deletions coreneuron/mechanism/mech/enginemech.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,11 @@ int corenrn_embedded_run(int nthread,
mk_mech_init(argc, argv);

// initialize extra arguments built into special-core
coreneuron::modl_reg();

static bool modl_reg_called = false;
if (!modl_reg_called) {
coreneuron::modl_reg();
modl_reg_called = true;
}
// run simulation
run_solve_core(argc, argv);

Expand Down