Skip to content

Commit 5023910

Browse files
committed
Optimize computation in iaf_psc_alpha_ps model
Replace FP divides with FP multiplies and pre-compute loop invariants. Similar to nest#3304
1 parent 589d7a7 commit 5023910

File tree

2 files changed

+32
-12
lines changed

2 files changed

+32
-12
lines changed

models/iaf_psc_alpha_ps.cpp

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ nest::iaf_psc_alpha_ps::Parameters_::Parameters_()
8585
, U_min_( -std::numeric_limits< double >::infinity() ) // mV
8686
, U_reset_( -70.0 - E_L_ ) // mV, rel to E_L_
8787
{
88+
compute_local_();
8889
}
8990

9091
nest::iaf_psc_alpha_ps::State_::State_()
@@ -187,9 +188,21 @@ nest::iaf_psc_alpha_ps::Parameters_::set( const DictionaryDatum& d, Node* node )
187188
throw BadProperty( "All time constants must be strictly positive." );
188189
}
189190

191+
compute_local_();
192+
190193
return delta_EL;
191194
}
192195

196+
void
197+
nest::iaf_psc_alpha_ps::Parameters_::compute_local_()
198+
{
199+
// pre-compute inverse member variables for speed
200+
inv_c_m_ = 1.0 / c_m_;
201+
inv_tau_m_ = 1.0 / tau_m_;
202+
inv_tau_syn_ex_ = 1.0 / tau_syn_ex_;
203+
inv_tau_syn_in_ = 1.0 / tau_syn_in_;
204+
}
205+
193206
void
194207
nest::iaf_psc_alpha_ps::State_::get( DictionaryDatum& d, const Parameters_& p ) const
195208
{
@@ -268,15 +281,15 @@ nest::iaf_psc_alpha_ps::pre_run_hook()
268281

269282
V_.h_ms_ = Time::get_resolution().get_ms();
270283

271-
V_.psc_norm_ex_ = 1.0 * numerics::e / P_.tau_syn_ex_;
272-
V_.psc_norm_in_ = 1.0 * numerics::e / P_.tau_syn_in_;
284+
V_.psc_norm_ex_ = 1.0 * numerics::e * P_.inv_tau_syn_ex_;
285+
V_.psc_norm_in_ = 1.0 * numerics::e * P_.inv_tau_syn_in_;
273286

274287
// pre-compute matrix for full time step
275-
V_.expm1_tau_m_ = numerics::expm1( -V_.h_ms_ / P_.tau_m_ );
276-
V_.exp_tau_syn_ex_ = std::exp( -V_.h_ms_ / P_.tau_syn_ex_ );
277-
V_.exp_tau_syn_in_ = std::exp( -V_.h_ms_ / P_.tau_syn_in_ );
288+
V_.expm1_tau_m_ = numerics::expm1( -V_.h_ms_ * P_.inv_tau_m_ );
289+
V_.exp_tau_syn_ex_ = std::exp( -V_.h_ms_ * P_.inv_tau_syn_ex_ );
290+
V_.exp_tau_syn_in_ = std::exp( -V_.h_ms_ * P_.inv_tau_syn_in_ );
278291

279-
V_.P30_ = -P_.tau_m_ / P_.c_m_ * V_.expm1_tau_m_;
292+
V_.P30_ = -P_.tau_m_ * P_.inv_c_m_ * V_.expm1_tau_m_;
280293
// these are determined according to a numeric stability criterion
281294
propagator_ex_ = IAFPropagatorAlpha( P_.tau_syn_ex_, P_.tau_m_, P_.c_m_ );
282295
std::tie( V_.P31_ex_, V_.P32_ex_ ) = propagator_ex_.evaluate( V_.h_ms_ );
@@ -500,9 +513,9 @@ nest::iaf_psc_alpha_ps::propagate_( const double dt )
500513
// V_m_ remains unchanged at 0.0 while neuron is refractory
501514
if ( not S_.is_refractory_ )
502515
{
503-
const double expm1_tau_m = numerics::expm1( -dt / P_.tau_m_ );
516+
const double expm1_tau_m = numerics::expm1( -dt * P_.inv_tau_m_ );
504517

505-
const double ps_P30 = -P_.tau_m_ / P_.c_m_ * expm1_tau_m;
518+
const double ps_P30 = -P_.tau_m_ * P_.inv_c_m_ * expm1_tau_m;
506519

507520
double ps_P31_ex;
508521
double ps_P32_ex;
@@ -518,8 +531,8 @@ nest::iaf_psc_alpha_ps::propagate_( const double dt )
518531
S_.V_m_ = ( S_.V_m_ < P_.U_min_ ? P_.U_min_ : S_.V_m_ );
519532
}
520533

521-
const double ps_e_TauSyn_ex = std::exp( -dt / P_.tau_syn_ex_ );
522-
const double ps_e_TauSyn_in = std::exp( -dt / P_.tau_syn_in_ );
534+
const double ps_e_TauSyn_ex = std::exp( -dt * P_.inv_tau_syn_ex_ );
535+
const double ps_e_TauSyn_in = std::exp( -dt * P_.inv_tau_syn_in_ );
523536

524537
// now the synaptic components
525538
S_.I_ex_ = ps_e_TauSyn_ex * dt * S_.dI_ex_ + ps_e_TauSyn_ex * S_.I_ex_;
@@ -578,9 +591,9 @@ nest::iaf_psc_alpha_ps::emit_instant_spike_( Time const& origin, const long lag,
578591
double
579592
nest::iaf_psc_alpha_ps::threshold_distance( double t_step ) const
580593
{
581-
const double expm1_tau_m = numerics::expm1( -t_step / P_.tau_m_ );
594+
const double expm1_tau_m = numerics::expm1( -t_step * P_.inv_tau_m_ );
582595

583-
const double ps_P30 = -P_.tau_m_ / P_.c_m_ * expm1_tau_m;
596+
const double ps_P30 = -P_.tau_m_ * P_.inv_c_m_ * expm1_tau_m;
584597

585598
double ps_P31_ex;
586599
double ps_P32_ex;

models/iaf_psc_alpha_ps.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,13 +291,17 @@ class iaf_psc_alpha_ps : public ArchivingNode
291291

292292
/** Membrane time constant in ms. */
293293
double tau_m_;
294+
double inv_tau_m_; /* inverse of tau_m_ */
294295

295296
/** Time constant of synaptic current in ms. */
296297
double tau_syn_ex_;
297298
double tau_syn_in_;
299+
double inv_tau_syn_ex_; /* inverse of tau_syn_ex_ */
300+
double inv_tau_syn_in_; /* inverse of tau_syn_in_ */
298301

299302
/** Membrane capacitance in pF. */
300303
double c_m_;
304+
double inv_c_m_; /* inverse of c_m_ */
301305

302306
/** Refractory period in ms. */
303307
double t_ref_;
@@ -330,6 +334,9 @@ class iaf_psc_alpha_ps : public ArchivingNode
330334
* @returns Change in reversal potential E_L, to be passed to State_::set()
331335
*/
332336
double set( const DictionaryDatum&, Node* );
337+
338+
/** Used for pre-computing member variables for performance */
339+
void compute_local_();
333340
};
334341

335342
// ----------------------------------------------------------------

0 commit comments

Comments
 (0)