Skip to content

Vectorization implementation in nestkernel #2372

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 46 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
ca2aaa9
first working prototype
med-ayssar Apr 17, 2022
6877103
Support n threads
med-ayssar Apr 18, 2022
51509bd
Fix converting Node instance to Proxy instance
med-ayssar Apr 20, 2022
5dd7d94
Copy vectorized model
med-ayssar Apr 21, 2022
6f98928
Fix headers
med-ayssar Apr 23, 2022
a200143
Add param name
med-ayssar Apr 23, 2022
7457e16
Add another param name
med-ayssar Apr 23, 2022
a636a90
Merge branch 'nest_with_vectors' of github.com:med-ayssar/nest-simula…
med-ayssar Apr 23, 2022
a73dd04
Add space in header
med-ayssar Apr 23, 2022
1192c59
Merge branch 'master' into nest_with_vectors
med-ayssar Apr 23, 2022
ef7c762
Replace calibrate with pre_run_hook
med-ayssar Apr 23, 2022
ceeab95
Fix clang format after master merge
med-ayssar Apr 23, 2022
cf22551
Shift if clause block
med-ayssar Apr 23, 2022
ddb2a5f
remove unused param
med-ayssar Apr 23, 2022
262b0c3
Remove extra space
med-ayssar Apr 23, 2022
ac9ef23
Fix format
med-ayssar Apr 23, 2022
5a11000
Reduce number of Wunused-parameter
med-ayssar Apr 23, 2022
7054398
Fix formatting errors
med-ayssar Apr 23, 2022
6832327
Use auto formatter in vscode
med-ayssar Apr 23, 2022
9fc9de6
Vscode auto formatter failed
med-ayssar Apr 23, 2022
9813cfb
Remove all unused vars in functions decleration
med-ayssar Apr 23, 2022
e61fc6b
Remove auto format on save
med-ayssar Apr 23, 2022
8a5a4f5
Use Atom editor
med-ayssar Apr 23, 2022
f2e1708
Remove -Wunused-parameter from vectorized_node.cpp
med-ayssar Apr 23, 2022
c8f9555
Make func params in one line
med-ayssar Apr 23, 2022
b5657ed
Break line in function
med-ayssar Apr 23, 2022
82fc87b
Remove last three -Wunused-parameter
med-ayssar Apr 23, 2022
33c37e3
Remove Line break
med-ayssar Apr 23, 2022
3493c04
Fix for Macos build
med-ayssar Apr 23, 2022
b822be7
Remove extra space
med-ayssar Apr 23, 2022
7e1ad93
Merge branch 'nest:master' into nest_with_vectors
med-ayssar May 4, 2022
e616050
make get_state_element virtual
med-ayssar May 7, 2022
0dd2a2a
Merge branch 'nest_with_vectors' of github.com:med-ayssar/nest-simula…
med-ayssar May 7, 2022
25ced5a
Merge with current master state
med-ayssar Nov 30, 2022
c60e5c2
Fix staticcheck
med-ayssar Dec 1, 2022
fb6131c
Use clang-format in VS code
med-ayssar Dec 1, 2022
ced7ec9
Merge branch 'master' into nest_with_vectors
med-ayssar Jan 3, 2023
e541c65
Avoid full_build failure
med-ayssar Jan 3, 2023
889d3a2
Fix static code erros
med-ayssar Jan 3, 2023
09f33ce
Remove old code
med-ayssar Jan 3, 2023
78d9583
Split nodes creation
med-ayssar Jan 3, 2023
7d91752
Fix copyModel function
med-ayssar Jan 4, 2023
0ad1c29
Fix merge conflicts
med-ayssar Jan 4, 2023
8f20f75
Apply staticcode analysis fixes
med-ayssar Jan 4, 2023
c6d1d20
Fix failling pipeline
med-ayssar Jan 4, 2023
2c6d47e
add override keyword
med-ayssar Jan 4, 2023
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
4 changes: 4 additions & 0 deletions nestkernel/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,10 @@ set ( nestkernel_sources
position.h
spatial.h spatial.cpp
stimulation_backend.h
vectorized_node.h vectorized_node.cpp
jit_node.h jit_node.cpp
structural_plasticity_vector.h structural_plasticity_vector.cpp
archiving_vector.h archiving_vector.cpp
)


Expand Down
283 changes: 283 additions & 0 deletions nestkernel/archiving_vector.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,283 @@
/*
* archiving_vector.cpp
*
* This file is part of NEST.
*
* Copyright (C) 2004 The NEST Initiative
*
* NEST is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* NEST is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with NEST. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "archiving_vector.h"

// Includes from nestkernel:
#include "kernel_manager.h"

// Includes from sli:
#include "dictutils.h"
#include "structural_plasticity_node.h"

namespace nest
{

nest::ArchivingVector::ArchivingVector()
: n_incoming_( 0 )
, Kminus_( 0 )
, Kminus_triplet_( 0 )
, tau_minus_( 0 )
, tau_minus_inv_( 0 )
, tau_minus_triplet_( 0 )
, tau_minus_triplet_inv_( 0 )
, max_delay_( 0 )
, trace_( 0 )
, last_spike_( 0 )
, history_( 0 )
{
}
// nest::ArchivingVector::ArchivingVector( const ArchivingVector& n ) : StructuralPlasticityVector(n)
// {
// throw std::runtime_error( "ArchivingVector shouldn't be cloned" );
// }

void
ArchivingVector::resize( index extended_space, index thread_id )
{
index total_space = size();

n_incoming_.resize( total_space, 0 );
Kminus_triplet_.resize( total_space, 0.0 );
Kminus_.resize( total_space, 0.0 );
tau_minus_.resize( total_space, 20.0 );
tau_minus_inv_.resize( total_space, 1 / 20.0 );
tau_minus_triplet_.resize( total_space, 110.0 );
tau_minus_triplet_inv_.resize( total_space, 1 / 110.0 );
max_delay_.resize( total_space, 0.0 );
trace_.resize( total_space, 0.0 );
last_spike_.resize( total_space, -1.0 );
history_.resize( total_space, std::deque< histentry >() );


StructuralPlasticityVector::resize( extended_space, thread_id );
}

void
nest::ArchivingVector::register_stdp_connection( double t_first_read, double delay, index local_id )
{
for ( std::deque< histentry >::iterator runner = history_.at( local_id ).begin();
runner != history_.at( local_id ).end()
and ( t_first_read - runner->t_ > -1.0 * kernel().connection_manager.get_stdp_eps() );
++runner )
{
( runner->access_counter_ )++;
}

n_incoming_.at( local_id )++;

max_delay_.at( local_id ) = std::max( delay, max_delay_.at( local_id ) );
}
double
nest::ArchivingVector::get_K_value( double t, index local_id )
{
// case when the neuron has not yet spiked
if ( history_.at( local_id ).empty() )
{
trace_.at( local_id ) = 0.;
return trace_.at( local_id );
}

// search for the latest post spike in the history buffer that came strictly
// before `t`
int i = history_.at( local_id ).size() - 1;
while ( i >= 0 )
{
if ( t - history_.at( local_id )[ i ].t_ > kernel().connection_manager.get_stdp_eps() )
{
trace_.at( local_id ) = ( history_.at( local_id )[ i ].Kminus_
* std::exp( ( history_.at( local_id )[ i ].t_ - t ) * tau_minus_inv_.at( local_id ) ) );
return trace_.at( local_id );
}
--i;
}

// this case occurs when the trace was requested at a time precisely at or
// before the first spike in the history
trace_.at( local_id ) = 0.;
return trace_.at( local_id );
}
void
nest::ArchivingVector::get_K_values( double t,
double& K_value,
double& nearest_neighbor_K_value,
double& K_triplet_value,
index local_id )
{
// case when the neuron has not yet spiked
if ( history_.at( local_id ).empty() )
{
K_triplet_value = Kminus_triplet_.at( local_id );
nearest_neighbor_K_value = Kminus_.at( local_id );
K_value = Kminus_.at( local_id );
return;
}

// search for the latest post spike in the history buffer that came strictly
// before `t`
int i = history_.at( local_id ).size() - 1;
while ( i >= 0 )
{
if ( t - history_.at( local_id )[ i ].t_ > kernel().connection_manager.get_stdp_eps() )
{
K_triplet_value = ( history_.at( local_id )[ i ].Kminus_triplet_
* std::exp( ( history_.at( local_id )[ i ].t_ - t ) * tau_minus_triplet_inv_.at( local_id ) ) );
K_value = ( history_.at( local_id )[ i ].Kminus_
* std::exp( ( history_.at( local_id )[ i ].t_ - t ) * tau_minus_inv_.at( local_id ) ) );
nearest_neighbor_K_value = std::exp( ( history_.at( local_id )[ i ].t_ - t ) * tau_minus_inv_.at( local_id ) );
return;
}
--i;
}

// this case occurs when the trace was requested at a time precisely at or
// before the first spike in the history
K_triplet_value = 0.0;
nearest_neighbor_K_value = 0.0;
K_value = 0.0;
}
void
nest::ArchivingVector::get_history( double t1,
double t2,
std::deque< histentry >::iterator* start,
std::deque< histentry >::iterator* finish,
index local_id )
{
*finish = history_.at( local_id ).end();
if ( history_.at( local_id ).empty() )
{
*start = *finish;
return;
}
std::deque< histentry >::reverse_iterator runner = history_.at( local_id ).rbegin();
const double t2_lim = t2 + kernel().connection_manager.get_stdp_eps();
const double t1_lim = t1 + kernel().connection_manager.get_stdp_eps();
while ( runner != history_.at( local_id ).rend() and runner->t_ >= t2_lim )
{
++runner;
}
*finish = runner.base();
while ( runner != history_.at( local_id ).rend() and runner->t_ >= t1_lim )
{
runner->access_counter_++;
++runner;
}
*start = runner.base();
}


void
nest::ArchivingVector::set_spiketime( const Time& t_sp, index local_id, double offset )
{
StructuralPlasticityVector::set_spiketime( t_sp, local_id, offset );

const double t_sp_ms = t_sp.get_ms() - offset;

if ( n_incoming_.at( local_id ) )
{
// prune all spikes from history which are no longer needed
// only remove a spike if:
// - its access counter indicates it has been read out by all connected
// STDP synapses, and
// - there is another, later spike, that is strictly more than
// (max_delay_ + eps) away from the new spike (at t_sp_ms)
while ( history_.at( local_id ).size() > 1 )
{
const double next_t_sp = history_.at( local_id )[ 1 ].t_;
if ( history_.at( local_id ).front().access_counter_ >= n_incoming_.at( local_id )
and t_sp_ms - next_t_sp > max_delay_.at( local_id ) + kernel().connection_manager.get_stdp_eps() )
{
history_.at( local_id ).pop_front();
}
else
{
break;
}
}
// update spiking history
Kminus_.at( local_id ) =
Kminus_.at( local_id ) * std::exp( ( last_spike_.at( local_id ) - t_sp_ms ) * tau_minus_inv_.at( local_id ) )
+ 1.0;
Kminus_triplet_.at( local_id ) = Kminus_triplet_.at( local_id )
* std::exp( ( last_spike_.at( local_id ) - t_sp_ms ) * tau_minus_triplet_inv_.at( local_id ) )
+ 1.0;
last_spike_.at( local_id ) = t_sp_ms;
history_.at( local_id )
.push_back( histentry( last_spike_.at( local_id ), Kminus_.at( local_id ), Kminus_triplet_.at( local_id ), 0 ) );
}
else
{
last_spike_.at( local_id ) = t_sp_ms;
}
}
void
nest::ArchivingVector::get_status( DictionaryDatum& d, index local_id ) const
{
def< double >( d, names::t_spike, get_spiketime_ms( local_id ) );
def< double >( d, names::tau_minus, tau_minus_.at( local_id ) );
def< double >( d, names::tau_minus_triplet, tau_minus_triplet_.at( local_id ) );
def< double >( d, names::post_trace, trace_.at( local_id ) );
#ifdef DEBUG_ARCHIVER
def< int >( d, names::archiver_length, history_.at( local_id ).size() );
#endif

// add status dict items from the parent class
StructuralPlasticityVector::get_status( d, local_id );
}
void
nest::ArchivingVector::set_status( const DictionaryDatum& d, index local_id )
{
// We need to preserve values in case invalid values are set
double new_tau_minus = tau_minus_.at( local_id );
double new_tau_minus_triplet = tau_minus_triplet_.at( local_id );
updateValue< double >( d, names::tau_minus, new_tau_minus );
updateValue< double >( d, names::tau_minus_triplet, new_tau_minus_triplet );

if ( new_tau_minus <= 0.0 or new_tau_minus_triplet <= 0.0 )
{
throw BadProperty( "All time constants must be strictly positive." );
}

StructuralPlasticityVector::set_status( d, local_id );

// do the actual update
tau_minus_.at( local_id ) = new_tau_minus;
tau_minus_triplet_.at( local_id ) = new_tau_minus_triplet;
tau_minus_inv_.at( local_id ) = 1. / new_tau_minus;
tau_minus_triplet_inv_.at( local_id ) = 1. / new_tau_minus_triplet;

// check, if to clear spike history and K_minus
bool clear = false;
updateValue< bool >( d, names::clear, clear );
if ( clear )
{
clear_history( local_id );
}
}
void
nest::ArchivingVector::clear_history( index local_id )
{
last_spike_.at( local_id ) = -1.0;
Kminus_.at( local_id ) = 0.0;
Kminus_triplet_.at( local_id ) = 0.0;
history_.at( local_id ).clear();
}
} // end of namespace nest
Loading