From b006bc1661fdd293dc1cfbca2f114cf42d8e7f4b Mon Sep 17 00:00:00 2001 From: gmtiddia Date: Wed, 24 Jun 2026 11:01:52 +0100 Subject: [PATCH 1/5] avoid calibration error if no connections with poisson generator are instantiated --- src/poiss_gen.cu | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/poiss_gen.cu b/src/poiss_gen.cu index 5723e43d1..14dd0db4b 100644 --- a/src/poiss_gen.cu +++ b/src/poiss_gen.cu @@ -132,6 +132,12 @@ poiss_gen::SendDirectSpikes( long long time_idx ) int poiss_gen::Calibrate( double, float ) { + // if the device is not connected to any other node, the calibration continues without rising errors + if ( n_dir_conn_ == 0 ) + { + return 0; + } + CUDAMALLOCCTRL( "&d_curand_state_", &d_curand_state_, n_dir_conn_ * sizeof( curandState ) ); unsigned int grid_dim_x, grid_dim_y; From 364a4de25795f1675203b48ebc47b309ca466d52 Mon Sep 17 00:00:00 2001 From: gmtiddia Date: Wed, 24 Jun 2026 13:43:26 +0100 Subject: [PATCH 2/5] added warning message --- src/poiss_gen.cu | 1 + 1 file changed, 1 insertion(+) diff --git a/src/poiss_gen.cu b/src/poiss_gen.cu index 14dd0db4b..5559ba16c 100644 --- a/src/poiss_gen.cu +++ b/src/poiss_gen.cu @@ -135,6 +135,7 @@ poiss_gen::Calibrate( double, float ) // if the device is not connected to any other node, the calibration continues without rising errors if ( n_dir_conn_ == 0 ) { + std::cout << "\tWarning: Poisson generator devices created but not used.\n"; return 0; } From 0480ed6b45d2a1944a6e36f009a7be6672f22a70 Mon Sep 17 00:00:00 2001 From: Gianmarco Tiddia Date: Thu, 25 Jun 2026 10:36:55 +0200 Subject: [PATCH 3/5] remove tab from warning message --- src/poiss_gen.cu | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/poiss_gen.cu b/src/poiss_gen.cu index 5559ba16c..9a1d545bc 100644 --- a/src/poiss_gen.cu +++ b/src/poiss_gen.cu @@ -135,7 +135,7 @@ poiss_gen::Calibrate( double, float ) // if the device is not connected to any other node, the calibration continues without rising errors if ( n_dir_conn_ == 0 ) { - std::cout << "\tWarning: Poisson generator devices created but not used.\n"; + std::cout << "Warning: Poisson generator devices created but not used.\n"; return 0; } From 58d782c7968d07c3cf4864d368212c2036b4ab39 Mon Sep 17 00:00:00 2001 From: gmtiddia Date: Thu, 25 Jun 2026 09:46:24 +0100 Subject: [PATCH 4/5] adding exception for avoiding errors for non connected poisson generators --- src/input_spike_buffer.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/input_spike_buffer.h b/src/input_spike_buffer.h index 5931c2584..715c3dbd1 100644 --- a/src/input_spike_buffer.h +++ b/src/input_spike_buffer.h @@ -816,6 +816,11 @@ ConnectionTemplate< ConnKeyT, ConnStructT >::sendDirectSpikes( long long time_id void* d_poiss_key_array, curandState* d_curand_state ) { + if (n_dir_conn == 0) + { + return 0; + } + unsigned int grid_dim_x, grid_dim_y; if ( n_dir_conn < 65536 * 1024 ) From e95f14e3e0ec87e902ef66389f5be7be04633b10 Mon Sep 17 00:00:00 2001 From: Gianmarco Tiddia Date: Thu, 25 Jun 2026 10:53:39 +0200 Subject: [PATCH 5/5] added python test to check that simulation does not fail in case of unused devices --- .../test_brunel_list_extra_poisson_gen.py | 154 ++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 python/tests/static_tests/test_brunel_list_extra_poisson_gen.py diff --git a/python/tests/static_tests/test_brunel_list_extra_poisson_gen.py b/python/tests/static_tests/test_brunel_list_extra_poisson_gen.py new file mode 100644 index 000000000..646d0f569 --- /dev/null +++ b/python/tests/static_tests/test_brunel_list_extra_poisson_gen.py @@ -0,0 +1,154 @@ +import sys +import math +import ctypes +import nestgpu as ngpu +from random import randrange +import numpy as np + +order = 200 +n_test = 100 + +expected_rate = 30.78 +print("Building ...") + +ngpu.SetKernelStatus("rnd_seed", 1234) # seed for GPU random numbers + +n_receptors = 2 + +NE = 4 * order # number of excitatory neurons +NI = 1 * order # number of inhibitory neurons +n_neurons = NE + NI # number of neurons in total + +CE = 800 # number of excitatory synapses per neuron +CI = CE//4 # number of inhibitory synapses per neuron + +Wex = 0.05 +Win = 0.35 + +# poisson generator parameters +poiss_rate = 20000.0 # poisson signal rate in Hz +poiss_weight = 0.37 +poiss_delay = 0.2 # poisson signal delay in ms + +# create poisson generator +pg = ngpu.Create("poisson_generator") +ngpu.SetStatus(pg, "rate", poiss_rate) +pg_list = pg.ToList() +# here an additional pg is created and not connected to test +# that the simulation does not fail in case of unconnected devices +pg2 = ngpu.Create("poisson_generator") + +# Create n_neurons neurons with n_receptor receptor ports +neuron = ngpu.Create("aeif_cond_beta_multisynapse", n_neurons, n_receptors) +exc_neuron = neuron[0:NE] # excitatory neurons +inh_neuron = neuron[NE:n_neurons] # inhibitory neurons +neuron_list = neuron.ToList() +exc_neuron_list = exc_neuron.ToList() +inh_neuron_list = inh_neuron.ToList() + +# receptor parameters +E_rev = [0.0, -85.0] +tau_decay = [1.0, 1.0] +tau_rise = [1.0, 1.0] +ngpu.SetStatus(neuron, {"E_rev":E_rev, "tau_decay":tau_decay, + "tau_rise":tau_rise}) + + +mean_delay = 0.5 +std_delay = 0.25 +min_delay = 0.1 +# Excitatory connections +# connect excitatory neurons to port 0 of all neurons +# normally distributed delays, weight Wex and CE connections per neuron +exc_conn_dict={"rule": "fixed_indegree", "indegree": CE} +exc_syn_dict={"weight": Wex, "delay": {"distribution":"normal_clipped", + "mu":mean_delay, "low":min_delay, + "high":mean_delay+3*std_delay, + "sigma":std_delay}, "receptor":0} +ngpu.Connect(exc_neuron, neuron_list, exc_conn_dict, exc_syn_dict) + +# Inhibitory connections +# connect inhibitory neurons to port 1 of all neurons +# normally distributed delays, weight Win and CI connections per neuron +inh_conn_dict={"rule": "fixed_indegree", "indegree": CI} +inh_syn_dict={"weight": Win, "delay":{"distribution":"normal_clipped", + "mu":mean_delay, "low":min_delay, + "high":mean_delay+3*std_delay, + "sigma":std_delay}, "receptor":1} +ngpu.Connect(inh_neuron_list, exc_neuron_list, inh_conn_dict, inh_syn_dict) +ngpu.Connect(inh_neuron_list, inh_neuron, inh_conn_dict, inh_syn_dict) + +#connect poisson generator to port 0 of all neurons +pg_conn_dict={"rule": "all_to_all"} +pg_syn_dict={"weight": poiss_weight, "delay": poiss_delay, + "receptor":0} + +ngpu.Connect(pg_list, neuron_list, pg_conn_dict, pg_syn_dict) + +i_neuron_list = [neuron[0], neuron[n_neurons-1]] +i_receptor_list = [0, 0] +var_name_list = ["spike", "spike"] + +for i in range(n_test-2): + i_neuron_list.append(neuron[randrange(n_neurons)]) + i_receptor_list.append(0) + var_name_list.append("spike") + +# create multimeter record of spikes +record = ngpu.CreateRecord("", var_name_list, i_neuron_list, i_receptor_list) + +ngpu.Simulate() + +data_list = ngpu.GetRecordData(record) + +for i in range(1000): + conn_id = ngpu.GetConnections(i+1) + n_out_conn = len(conn_id) + if (n_out_conn!=NE+NI): + print("Expected number of out connections per neuron: ", NE+NI) + print("Number of out connections of neuron ", i + 1, ": ", \ + n_out_conn) + #sys.exit(1) + + +for i in range(10): + i_target = randrange(n_neurons) + conn_id = ngpu.GetConnections(target=i_target+1) + n_in_conn = len(conn_id) + if (n_in_conn!=NE+NI+1): + print("Expected number of in connections per neuron: ", NE+NI+1) + print("Number of in connections of neuron ", i_target, ": ", \ + n_in_conn) + #sys.exit(1) + + +row_sum = list(data_list[0]) +for row in data_list[1:len(data_list)]: + for i in range(len(row_sum)): + row_sum[i] = row_sum[i] + row[i] + +spike = row_sum[1:len(row_sum)] +spike_arr = np.array(spike) + +min_spike_num = np.min(spike_arr) +max_spike_num = np.max(spike_arr) +if (min_spike_num < expected_rate - 3.0*math.sqrt(expected_rate)): + print ("Expected rate: ", expected_rate) + print("Min rate :", min_spike_num) + sys.exit(1) + +if (max_spike_num > expected_rate + 3.0*math.sqrt(expected_rate)): + print ("Expected rate: ", expected_rate) + print("Max rate :", max_spike_num) + sys.exit(1) + +mean_spike_num = np.mean(spike_arr) +diff = abs(mean_spike_num - expected_rate) +max_diff = 3.0*np.sqrt(expected_rate)/np.sqrt(n_test) +print ("Expected rate: ", expected_rate) +print("Mean rate: ", mean_spike_num) +if diff > max_diff: + sys.exit(1) +else: + sys.exit(0) +