Skip to content
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 lib/include/global.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ namespace GENN_PREFERENCES {
extern bool showPtxInfo; //!< Request that PTX assembler information be displayed for each CUDA kernel during compilation
extern bool buildSharedLibrary; //!< Should generated code and Makefile build into a shared library e.g. for use in SpineML simulator
extern bool autoInitSparseVars; //!< Previously, variables associated with sparse synapse populations were not automatically initialised. If this flag is set this now occurs in the initMODEL_NAME function and copyStateToDevice is deferred until here
extern bool mergePostsynapticModels; //!< Should compatible postsynaptic models and dendritic delay buffers be merged? This can significantly reduce the cost of updating neuron population but means that per-synapse group inSyn arrays can not be retrieved
extern VarMode defaultVarMode; //!< What is the default behaviour for model state variables? Historically, everything was allocated on both host AND device and initialised on HOST.
extern double asGoodAsZero; //!< Global variable that is used when detecting close to zero values, for example when setting sparse connectivity from a dense matrix
extern int defaultDevice; //! default GPU device; used to determine which GPU to use if chooseDevice is 0 (off)
Expand Down
5 changes: 5 additions & 0 deletions lib/include/neuronGroup.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@ class NeuronGroup
void initDerivedParams(double dt);
void calcSizes(unsigned int blockSize, unsigned int &idStart, unsigned int &paddedIDStart);

//! Merge incoming postsynaptic models
void mergeIncomingPSM();

//! add input current source
void injectCurrent(CurrentSource *source);

Expand All @@ -120,6 +123,7 @@ class NeuronGroup

//! Gets pointers to all synapse groups which provide input to this neuron group
const std::vector<SynapseGroup*> &getInSyn() const{ return m_InSyn; }
const std::vector<std::pair<SynapseGroup*, std::vector<SynapseGroup*>>> &getMergedInSyn() const{ return m_MergedInSyn; }

//! Gets pointers to all synapse groups emanating from this neuron group
const std::vector<SynapseGroup*> &getOutSyn() const{ return m_OutSyn; }
Expand Down Expand Up @@ -210,6 +214,7 @@ class NeuronGroup
std::vector<NewModels::VarInit> m_VarInitialisers;
std::vector<SynapseGroup*> m_InSyn;
std::vector<SynapseGroup*> m_OutSyn;
std::vector<std::pair<SynapseGroup*, std::vector<SynapseGroup*>>> m_MergedInSyn;
bool m_SpikeTimeRequired;
bool m_TrueSpikeRequired;
bool m_SpikeEventRequired;
Expand Down
2 changes: 1 addition & 1 deletion lib/include/standardGeneratedSections.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ void neuronSpikeEventTest(
const VarNameIterCtx &nmVars,
const ExtraGlobalParamNameIterCtx &nmExtraGlobalParams,
const std::string &localID,
const std::vector<FunctionTemplate> functions,
const std::vector<FunctionTemplate> &functions,
const std::string &ftype,
const std::string &rng);

Expand Down
22 changes: 11 additions & 11 deletions lib/include/standardSubstitutions.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ void postSynapseApplyInput(
const VarNameIterCtx &nmVars,
const DerivedParamNameIterCtx &nmDerivedParams,
const ExtraGlobalParamNameIterCtx &nmExtraGlobalParams, //!
const std::vector<FunctionTemplate> functions, //! Appropriate array of platform-specific function templates used to implement platform-specific functions e.g. gennrand_uniform
const std::vector<FunctionTemplate> &functions, //! Appropriate array of platform-specific function templates used to implement platform-specific functions e.g. gennrand_uniform
const std::string &ftype, //! Floating point type used by model e.g. "float"
const std::string &rng); //! Name of the RNG to use for any probabilistic operations

Expand All @@ -60,7 +60,7 @@ void postSynapseDecay(
const VarNameIterCtx &nmVars,
const DerivedParamNameIterCtx &nmDerivedParams,
const ExtraGlobalParamNameIterCtx &nmExtraGlobalParams,
const std::vector<FunctionTemplate> functions,
const std::vector<FunctionTemplate> &functions,
const std::string &ftype,
const std::string &rng);

Expand All @@ -71,7 +71,7 @@ void neuronThresholdCondition(
const VarNameIterCtx &nmVars,
const DerivedParamNameIterCtx &nmDerivedParams,
const ExtraGlobalParamNameIterCtx &nmExtraGlobalParams,
const std::vector<FunctionTemplate> functions,
const std::vector<FunctionTemplate> &functions,
const std::string &ftype,
const std::string &rng);

Expand All @@ -81,7 +81,7 @@ void neuronSim(
const VarNameIterCtx &nmVars,
const DerivedParamNameIterCtx &nmDerivedParams,
const ExtraGlobalParamNameIterCtx &nmExtraGlobalParams,
const std::vector<FunctionTemplate> functions,
const std::vector<FunctionTemplate> &functions,
const std::string &ftype,
const std::string &rng);

Expand All @@ -90,7 +90,7 @@ void neuronSpikeEventCondition(
const NeuronGroup &ng,
const VarNameIterCtx &nmVars,
const ExtraGlobalParamNameIterCtx &nmExtraGlobalParams,
const std::vector<FunctionTemplate> functions,
const std::vector<FunctionTemplate> &functions,
const std::string &ftype,
const std::string &rng);

Expand All @@ -100,7 +100,7 @@ void neuronReset(
const VarNameIterCtx &nmVars,
const DerivedParamNameIterCtx &nmDerivedParams,
const ExtraGlobalParamNameIterCtx &nmExtraGlobalParams,
const std::vector<FunctionTemplate> functions,
const std::vector<FunctionTemplate> &functions,
const std::string &ftype,
const std::string &rng);

Expand All @@ -112,7 +112,7 @@ void weightUpdateThresholdCondition(
const string &preIdx, //!< index of the pre-synaptic neuron to be accessed for _pre variables; differs for different Span)
const string &postIdx, //!< index of the post-synaptic neuron to be accessed for _post variables; differs for different Span)
const string &devPrefix,
const std::vector<FunctionTemplate> functions,
const std::vector<FunctionTemplate> &functions,
const std::string &ftype);

void weightUpdateSim(
Expand All @@ -124,7 +124,7 @@ void weightUpdateSim(
const string &preIdx, //!< index of the pre-synaptic neuron to be accessed for _pre variables; differs for different Span)
const string &postIdx, //!< index of the post-synaptic neuron to be accessed for _post variables; differs for different Span)
const string &devPrefix,
const std::vector<FunctionTemplate> functions,
const std::vector<FunctionTemplate> &functions,
const std::string &ftype);

void weightUpdateDynamics(
Expand All @@ -136,7 +136,7 @@ void weightUpdateDynamics(
const string &preIdx, //!< index of the pre-synaptic neuron to be accessed for _pre variables; differs for different Span)
const string &postIdx, //!< index of the post-synaptic neuron to be accessed for _post variables; differs for different Span)
const string &devPrefix,
const std::vector<FunctionTemplate> functions,
const std::vector<FunctionTemplate> &functions,
const std::string &ftype);

void weightUpdatePostLearn(
Expand All @@ -147,13 +147,13 @@ void weightUpdatePostLearn(
const string &preIdx, //!< index of the pre-synaptic neuron to be accessed for _pre variables; differs for different Span)
const string &postIdx, //!< index of the post-synaptic neuron to be accessed for _post variables; differs for different Span)
const string &devPrefix,
const std::vector<FunctionTemplate> functions,
const std::vector<FunctionTemplate> &functions,
const std::string &ftype);

std::string initVariable(
const NewModels::VarInit &varInit,
const std::string &varName,
const std::vector<FunctionTemplate> functions,
const std::vector<FunctionTemplate> &functions,
const std::string &ftype,
const std::string &rng);

Expand Down
12 changes: 12 additions & 0 deletions lib/include/synapseGroup.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ class SynapseGroup
void setSpikeEventRequired(bool req){ m_SpikeEventRequired = req; }
void setEventThresholdReTestRequired(bool req){ m_EventThresholdReTestRequired = req; }

void setPSModelMergeTarget(const std::string &targetName)
{
m_PSModelTargetName = targetName;
}

//!< Function to enable the use of zero-copied memory for a particular weight update model state variable (deprecated use SynapseGroup::setWUVarMode):
/*! May improve IO performance at the expense of kernel performance */
void setWUVarZeroCopyEnabled(const std::string &varName, bool enabled)
Expand Down Expand Up @@ -139,6 +144,9 @@ class SynapseGroup
const std::vector<NewModels::VarInit> &getPSVarInitialisers() const{ return m_PSVarInitialisers; }
const std::vector<double> getPSConstInitVals() const;

const std::string &getPSModelTargetName() const{ return m_PSModelTargetName; }
bool isPSModelMerged() const{ return m_PSModelTargetName != getName(); }

bool isZeroCopyEnabled() const;
bool isWUVarZeroCopyEnabled(const std::string &var) const{ return (getWUVarMode(var) & VarLocation::ZERO_COPY); }
bool isPSVarZeroCopyEnabled(const std::string &var) const{ return (getPSVarMode(var) & VarLocation::ZERO_COPY); }
Expand Down Expand Up @@ -272,4 +280,8 @@ class SynapseGroup

//!< Whether indidividual state variables of post synapse should use zero-copied memory
std::vector<VarMode> m_PSVarMode;

//! Name of the synapse group in which postsynaptic model is located
/*! This may not be the name of this group if it has been merged*/
std::string m_PSModelTargetName;
};
46 changes: 24 additions & 22 deletions lib/src/generateCPU.cc
Original file line number Diff line number Diff line change
Expand Up @@ -134,15 +134,15 @@ void generate_process_presynaptic_events_code_CPU(
string wCode = evnt ? wu->getEventCode() : wu->getSimCode();

if(sg.isDendriticDelayRequired()) {
functionSubstitute(wCode, "addToInSynDelay", 2, "denDelay" + sgName + "[" + sg.getDendriticDelayOffset("", "$(1)") + "ipost] += $(0)");
functionSubstitute(wCode, "addToInSynDelay", 2, "denDelay" + sg.getPSModelTargetName() + "[" + sg.getDendriticDelayOffset("", "$(1)") + "ipost] += $(0)");
}
else {
functionSubstitute(wCode, "addToInSyn", 1, "inSyn" + sgName + "[ipost] += $(0)");
functionSubstitute(wCode, "addToInSyn", 1, "inSyn" + sg.getPSModelTargetName() + "[ipost] += $(0)");

// **DEPRECATED**
os << ftype << " addtoinSyn;" << std::endl;
substitute(wCode, "$(updatelinsyn)", "$(inSyn) += $(addtoinSyn)");
substitute(wCode, "$(inSyn)", "inSyn" + sgName + "[ipost]");
substitute(wCode, "$(inSyn)", "inSyn" + sg.getPSModelTargetName() + "[ipost]");
}

substitute(wCode, "$(t)", "t");
Expand Down Expand Up @@ -265,7 +265,7 @@ void genNeuronFunction(const NNmodel &model, //!< Model description
}
os << std::endl;

if (n.second.getInSyn().size() > 0 || (nm->getSimCode().find("Isyn") != string::npos)) {
if (!n.second.getMergedInSyn().empty() || (nm->getSimCode().find("Isyn") != string::npos)) {
os << model.getPrecision() << " Isyn = 0;" << std::endl;
}

Expand All @@ -274,32 +274,33 @@ void genNeuronFunction(const NNmodel &model, //!< Model description
os << a.second.first << " " << a.first << " = " << a.second.second << ";" << std::endl;
}

for(const auto *sg : n.second.getInSyn()) {
for(const auto &m : n.second.getMergedInSyn()) {
const auto *sg = m.first;
const auto *psm = sg->getPSModel();

// If dendritic delay is required
if(sg->isDendriticDelayRequired()) {
// Get reference to dendritic delay buffer input for this timestep
os << model.getPrecision() << " &denDelayFront" << sg->getName() << " = denDelay" + sg->getName() + "[" + sg->getDendriticDelayOffset("") + "n];" << std::endl;
os << model.getPrecision() << " &denDelayFront" << sg->getPSModelTargetName() << " = denDelay" + sg->getPSModelTargetName() + "[" + sg->getDendriticDelayOffset("") + "n];" << std::endl;

// Add delayed input from buffer into inSyn
os << "inSyn" + sg->getName() + "[n] += denDelayFront" << sg->getName() << ";" << std::endl;
os << "inSyn" + sg->getPSModelTargetName() + "[n] += denDelayFront" << sg->getPSModelTargetName() << ";" << std::endl;

// Zero delay buffer slot
os << "denDelayFront" << sg->getName() << " = " << model.scalarExpr(0.0) << ";" << std::endl;
os << "denDelayFront" << sg->getPSModelTargetName() << " = " << model.scalarExpr(0.0) << ";" << std::endl;
}

if (sg->getMatrixType() & SynapseMatrixWeight::INDIVIDUAL_PSM) {
for(const auto &v : psm->getVars()) {
os << v.second << " lps" << v.first << sg->getName();
os << " = " << v.first << sg->getName() << "[n];" << std::endl;
os << v.second << " lps" << v.first << sg->getPSModelTargetName();
os << " = " << v.first << sg->getPSModelTargetName() << "[n];" << std::endl;
}
}

// Apply substitutions to current converter code
string psCode = psm->getApplyInputCode();
substitute(psCode, "$(id)", "n");
substitute(psCode, "$(inSyn)", "inSyn" + sg->getName() + "[n]");
substitute(psCode, "$(inSyn)", "inSyn" + sg->getPSModelTargetName() + "[n]");
StandardSubstitutions::postSynapseApplyInput(psCode, sg, n.second,
nmVars, nmDerivedParams, nmExtraGlobalParams, cpuFunctions, model.getPrecision(), "rng");

Expand Down Expand Up @@ -409,7 +410,8 @@ void genNeuronFunction(const NNmodel &model, //!< Model description
// store the defined parts of the neuron state into the global state variables V etc
StandardGeneratedSections::neuronLocalVarWrite(os, n.second, nmVars, "", "n");

for(const auto *sg : n.second.getInSyn()) {
for(const auto &m : n.second.getMergedInSyn()) {
const auto *sg = m.first;
const auto *psm = sg->getPSModel();

string pdCode = psm->getDecayCode();
Expand Down Expand Up @@ -522,14 +524,14 @@ void genSynapseFunction(const NNmodel &model, //!< Model description

const std::string postIdx = "C" + s.first + ".ind[n]";
if(sg->isDendriticDelayRequired()) {
functionSubstitute(SDcode, "addToInSynDelay", 2, "denDelay" + s.first + "[" + sg->getDendriticDelayOffset("", "$(1)") + postIdx + "] += $(0)");
functionSubstitute(SDcode, "addToInSynDelay", 2, "denDelay" + sg->getPSModelTargetName() + "[" + sg->getDendriticDelayOffset("", "$(1)") + postIdx + "] += $(0)");
}
else {
functionSubstitute(SDcode, "addToInSyn", 1, "inSyn" + s.first + "[" + postIdx + "] += $(0)");
functionSubstitute(SDcode, "addToInSyn", 1, "inSyn" + sg->getPSModelTargetName() + "[" + postIdx + "] += $(0)");

// **DEPRECATED**
substitute(SDcode, "$(updatelinsyn)", "$(inSyn) += $(addtoinSyn)");
substitute(SDcode, "$(inSyn)", "inSyn" + s.first + "[" + postIdx + "]");
substitute(SDcode, "$(inSyn)", "inSyn" + sg->getPSModelTargetName() + "[" + postIdx + "]");
}

StandardSubstitutions::weightUpdateDynamics(SDcode, sg, wuVars, wuDerivedParams, wuExtraGlobalParams,
Expand Down Expand Up @@ -557,14 +559,14 @@ void genSynapseFunction(const NNmodel &model, //!< Model description

const std::string postIdx = "C" + s.first + ".ind[n]";
if(sg->isDendriticDelayRequired()) {
functionSubstitute(SDcode, "addToInSynDelay", 2, "denDelay" + s.first + "[" + sg->getDendriticDelayOffset("", "$(1)") + postIdx + "] += $(0)");
functionSubstitute(SDcode, "addToInSynDelay", 2, "denDelay" + sg->getPSModelTargetName() + "[" + sg->getDendriticDelayOffset("", "$(1)") + postIdx + "] += $(0)");
}
else {
functionSubstitute(SDcode, "addToInSyn", 1, "inSyn" + s.first + "[" + postIdx + "] += $(0)");
functionSubstitute(SDcode, "addToInSyn", 1, "inSyn" + sg->getPSModelTargetName() + "[" + postIdx + "] += $(0)");

// **DEPRECATED**
substitute(SDcode, "$(updatelinsyn)", "$(inSyn) += $(addtoinSyn)");
substitute(SDcode, "$(inSyn)", "inSyn" + s.first + "[" + postIdx + "]");
substitute(SDcode, "$(inSyn)", "inSyn" + sg->getPSModelTargetName() + "[" + postIdx + "]");
}

StandardSubstitutions::weightUpdateDynamics(SDcode, sg, wuVars, wuDerivedParams, wuExtraGlobalParams,
Expand All @@ -584,18 +586,18 @@ void genSynapseFunction(const NNmodel &model, //!< Model description
// substitute initial values as constants for synapse var names in synapseDynamics code
if (sg->getMatrixType() & SynapseMatrixWeight::INDIVIDUAL) {
name_substitutions(SDcode, "", wuVars.nameBegin, wuVars.nameEnd,
s.first + "[(i * " + to_string(sg->getTrgNeuronGroup()->getNumNeurons()) + ") + j]");
s.first + "[(i * " + to_string(sg->getTrgNeuronGroup()->getNumNeurons()) + ") + j]");
}

if(sg->isDendriticDelayRequired()) {
functionSubstitute(SDcode, "addToInSynDelay", 2, "denDelay" + s.first + "[" + sg->getDendriticDelayOffset("", "$(1)") + "j] += $(0)");
functionSubstitute(SDcode, "addToInSynDelay", 2, "denDelay" + sg->getPSModelTargetName() + "[" + sg->getDendriticDelayOffset("", "$(1)") + "j] += $(0)");
}
else {
functionSubstitute(SDcode, "addToInSyn", 1, "inSyn" + s.first + "[j] += $(0)");
functionSubstitute(SDcode, "addToInSyn", 1, "inSyn" + sg->getPSModelTargetName() + "[j] += $(0)");

// **DEPRECATED**
substitute(SDcode, "$(updatelinsyn)", "$(inSyn) += $(addtoinSyn)");
substitute(SDcode, "$(inSyn)", "inSyn" + s.first + "[j]");
substitute(SDcode, "$(inSyn)", "inSyn" + sg->getPSModelTargetName() + "[j]");
}

StandardSubstitutions::weightUpdateDynamics(SDcode, sg, wuVars, wuDerivedParams, wuExtraGlobalParams,
Expand Down
Loading