1 /*
2 * simulation_manager.cpp
3 *
4 * This file is part of NEST.
5 *
6 * Copyright (C) 2004 The NEST Initiative
7 *
8 * NEST is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * NEST is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with NEST. If not, see <http://www.gnu.org/licenses/>.
20 *
21 */
22
23 #include "simulation_manager.h"
24
25 // C includes:
26 #include <sys/time.h>
27
28 // C++ includes:
29 #include <limits>
30 #include <vector>
31
32 // Includes from libnestutil:
33 #include "compose.hpp"
34 #include "numerics.h"
35
36 // Includes from nestkernel:
37 #include "connection_manager_impl.h"
38 #include "event_delivery_manager.h"
39 #include "kernel_manager.h"
40
41 // Includes from sli:
42 #include "dictutils.h"
43
SimulationManager()44 nest::SimulationManager::SimulationManager()
45 : clock_( Time::tic( 0L ) )
46 , slice_( 0L )
47 , to_do_( 0L )
48 , to_do_total_( 0L )
49 , from_step_( 0L )
50 , to_step_( 0L ) // consistent with to_do_ == 0
51 , t_real_( 0L )
52 , prepared_( false )
53 , simulating_( false )
54 , simulated_( false )
55 , inconsistent_state_( false )
56 , print_time_( false )
57 , use_wfr_( true )
58 , wfr_comm_interval_( 1.0 )
59 , wfr_tol_( 0.0001 )
60 , wfr_max_iterations_( 15 )
61 , wfr_interpolation_order_( 3 )
62 , update_time_limit_( std::numeric_limits< double >::infinity() )
63 , min_update_time_( std::numeric_limits< double >::infinity() )
64 , max_update_time_( -std::numeric_limits< double >::infinity() )
65 {
66 }
67
68 void
initialize()69 nest::SimulationManager::initialize()
70 {
71 // set resolution, ensure clock is calibrated to new resolution
72 Time::reset_resolution();
73 clock_.calibrate();
74
75 prepared_ = false;
76 simulating_ = false;
77 simulated_ = false;
78 inconsistent_state_ = false;
79
80 reset_timers_for_preparation();
81 reset_timers_for_dynamics();
82 }
83
84 void
finalize()85 nest::SimulationManager::finalize()
86 {
87 nest::Time::reset_to_defaults();
88
89 clock_.set_to_zero(); // ensures consistent state
90 to_do_ = 0;
91 slice_ = 0;
92 from_step_ = 0;
93 to_step_ = 0; // consistent with to_do_ = 0
94 }
95
96 void
reset_timers_for_preparation()97 nest::SimulationManager::reset_timers_for_preparation()
98 {
99 sw_communicate_prepare_.reset();
100 #ifdef TIMER_DETAILED
101 sw_gather_target_data_.reset();
102 #endif
103 }
104
105 void
reset_timers_for_dynamics()106 nest::SimulationManager::reset_timers_for_dynamics()
107 {
108 sw_simulate_.reset();
109 #ifdef TIMER_DETAILED
110 sw_gather_spike_data_.reset();
111 sw_update_.reset();
112 #endif
113 }
114
115 void
set_status(const DictionaryDatum & d)116 nest::SimulationManager::set_status( const DictionaryDatum& d )
117 {
118 // Create an instance of time converter here to capture the current
119 // representation of time objects: TICS_PER_MS and TICS_PER_STEP
120 // will be stored in time_converter.
121 // This object can then be used to convert times in steps
122 // (e.g. Connection::delay_) or tics to the new representation.
123 // We pass this object to ConnectionManager::calibrate to update
124 // all time objects in the connection system to the new representation.
125 // MH 08-04-14
126 TimeConverter time_converter;
127
128 double time;
129 if ( updateValue< double >( d, names::biological_time, time ) )
130 {
131 if ( time != 0.0 )
132 {
133 throw BadProperty( "The simulation time can only be set to 0.0." );
134 }
135
136 if ( clock_ > TimeZero )
137 {
138 // reset only if time has passed
139 LOG( M_WARNING,
140 "SimulationManager::set_status",
141 "Simulation time reset to t=0.0. Resetting the simulation time is not "
142 "fully supported in NEST at present. Some spikes may be lost, and "
143 "stimulation devices may behave unexpectedly. PLEASE REVIEW YOUR "
144 "SIMULATION OUTPUT CAREFULLY!" );
145
146 clock_ = Time::step( 0 );
147 from_step_ = 0;
148 slice_ = 0;
149 // clear all old spikes
150 kernel().event_delivery_manager.configure_spike_data_buffers();
151 }
152 }
153
154 updateValue< bool >( d, names::print_time, print_time_ );
155
156 // tics_per_ms and resolution must come after local_num_thread /
157 // total_num_threads because they might reset the network and the time
158 // representation
159 double tics_per_ms = 0.0;
160 bool tics_per_ms_updated = updateValue< double >( d, names::tics_per_ms, tics_per_ms );
161 double resd = 0.0;
162 bool res_updated = updateValue< double >( d, names::resolution, resd );
163
164 if ( tics_per_ms_updated or res_updated )
165 {
166 if ( kernel().node_manager.size() > 0 )
167 {
168 LOG( M_ERROR,
169 "SimulationManager::set_status",
170 "Cannot change time representation after nodes have been created. "
171 "Please call ResetKernel first." );
172 throw KernelException();
173 }
174 else if ( has_been_simulated() ) // someone may have simulated empty network
175 {
176 LOG( M_ERROR,
177 "SimulationManager::set_status",
178 "Cannot change time representation after the network has been "
179 "simulated. Please call ResetKernel first." );
180 throw KernelException();
181 }
182 else if ( kernel().connection_manager.get_num_connections() != 0 )
183 {
184 LOG( M_ERROR,
185 "SimulationManager::set_status",
186 "Cannot change time representation after connections have been "
187 "created. Please call ResetKernel first." );
188 throw KernelException();
189 }
190 else if ( kernel().model_manager.has_user_models() or kernel().model_manager.has_user_prototypes() )
191 {
192 LOG( M_ERROR,
193 "SimulationManager::set_status",
194 "Cannot change time representation when user models have been "
195 "created. Please call ResetKernel first." );
196 throw KernelException();
197 }
198 else if ( kernel().model_manager.are_model_defaults_modified() )
199 {
200 LOG( M_ERROR,
201 "SimulationManager::set_status",
202 "Cannot change time representation after model defaults have "
203 "been modified. Please call ResetKernel first." );
204 throw KernelException();
205 }
206 else if ( res_updated and tics_per_ms_updated ) // only allow TICS_PER_MS to
207 // be changed together with
208 // resolution
209 {
210 if ( resd < 1.0 / tics_per_ms )
211 {
212 LOG( M_ERROR,
213 "SimulationManager::set_status",
214 "Resolution must be greater than or equal to one tic. Value "
215 "unchanged." );
216 throw KernelException();
217 }
218 else if ( not is_integer( resd * tics_per_ms ) )
219 {
220 LOG( M_ERROR,
221 "SimulationManager::set_status",
222 "Resolution must be a multiple of the tic length. Value unchanged." );
223 throw KernelException();
224 }
225 else
226 {
227 nest::Time::set_resolution( tics_per_ms, resd );
228 // adjust to new resolution
229 clock_.calibrate();
230 // adjust delays in the connection system to new resolution
231 kernel().connection_manager.calibrate( time_converter );
232 kernel().model_manager.calibrate( time_converter );
233 LOG( M_INFO, "SimulationManager::set_status", "tics per ms and resolution changed." );
234
235 // make sure that wfr communication interval is always greater or equal
236 // to resolution if no wfr is used explicitly set wfr_comm_interval
237 // to resolution because communication in every step is needed
238 if ( wfr_comm_interval_ < Time::get_resolution().get_ms() or not use_wfr_ )
239 {
240 wfr_comm_interval_ = Time::get_resolution().get_ms();
241 }
242 }
243 }
244 else if ( res_updated ) // only resolution changed
245 {
246 if ( resd < Time::get_ms_per_tic() )
247 {
248 LOG( M_ERROR,
249 "SimulationManager::set_status",
250 "Resolution must be greater than or equal to one tic. Value "
251 "unchanged." );
252 throw KernelException();
253 }
254 else if ( not is_integer( resd / Time::get_ms_per_tic() ) )
255 {
256 LOG( M_ERROR,
257 "SimulationManager::set_status",
258 "Resolution must be a multiple of the tic length. Value unchanged." );
259 throw KernelException();
260 }
261 else
262 {
263 Time::set_resolution( resd );
264 clock_.calibrate(); // adjust to new resolution
265 // adjust delays in the connection system to new resolution
266 kernel().connection_manager.calibrate( time_converter );
267 kernel().model_manager.calibrate( time_converter );
268 LOG( M_INFO, "SimulationManager::set_status", "Temporal resolution changed." );
269
270 // make sure that wfr communication interval is always greater or equal
271 // to resolution if no wfr is used explicitly set wfr_comm_interval
272 // to resolution because communication in every step is needed
273 if ( wfr_comm_interval_ < Time::get_resolution().get_ms() or not use_wfr_ )
274 {
275 wfr_comm_interval_ = Time::get_resolution().get_ms();
276 }
277 }
278 }
279 else
280 {
281 LOG( M_ERROR,
282 "SimulationManager::set_status",
283 "change of tics_per_step requires simultaneous specification of "
284 "resolution." );
285 throw KernelException();
286 }
287 }
288
289 // The decision whether the waveform relaxation is used
290 // must be set before nodes are created.
291 // Important: wfr_comm_interval_ may change depending on use_wfr_
292 bool wfr;
293 if ( updateValue< bool >( d, names::use_wfr, wfr ) )
294 {
295 if ( kernel().node_manager.size() > 0 )
296 {
297 LOG( M_ERROR,
298 "SimulationManager::set_status",
299 "Cannot enable/disable usage of waveform relaxation after nodes have "
300 "been created. Please call ResetKernel first." );
301 throw KernelException();
302 }
303 else
304 {
305 use_wfr_ = wfr;
306 // if no wfr is used explicitly set wfr_comm_interval to resolution
307 // because communication in every step is needed
308 if ( not use_wfr_ )
309 {
310 wfr_comm_interval_ = Time::get_resolution().get_ms();
311 }
312 }
313 }
314
315 // wfr_comm_interval_ can only be changed if use_wfr_ is true and before
316 // connections are created. If use_wfr_ is false wfr_comm_interval_ is set to
317 // the resolution whenever the resolution changes.
318 double wfr_interval;
319 if ( updateValue< double >( d, names::wfr_comm_interval, wfr_interval ) )
320 {
321 if ( not use_wfr_ )
322 {
323 LOG( M_ERROR,
324 "SimulationManager::set_status",
325 "Cannot set waveform communication interval when usage of waveform "
326 "relaxation is disabled. Set use_wfr to true first." );
327 throw KernelException();
328 }
329 else if ( kernel().connection_manager.get_num_connections() != 0 )
330 {
331 LOG( M_ERROR,
332 "SimulationManager::set_status",
333 "Cannot change waveform communication interval after connections have "
334 "been created. Please call ResetKernel first." );
335 throw KernelException();
336 }
337 else if ( wfr_interval < Time::get_resolution().get_ms() )
338 {
339 LOG( M_ERROR,
340 "SimulationManager::set_status",
341 "Communication interval of the waveform relaxation must be greater or "
342 "equal to the resolution of the simulation." );
343 throw KernelException();
344 }
345 else
346 {
347 LOG( M_INFO, "SimulationManager::set_status", "Waveform communication interval changed successfully. " );
348 wfr_comm_interval_ = wfr_interval;
349 }
350 }
351
352 // set the convergence tolerance for the waveform relaxation method
353 double tol;
354 if ( updateValue< double >( d, names::wfr_tol, tol ) )
355 {
356 if ( tol < 0.0 )
357 {
358 LOG( M_ERROR, "SimulationManager::set_status", "Tolerance must be zero or positive" );
359 throw KernelException();
360 }
361 else
362 {
363 wfr_tol_ = tol;
364 }
365 }
366
367 // set the maximal number of iterations for the waveform relaxation method
368 long max_iter;
369 if ( updateValue< long >( d, names::wfr_max_iterations, max_iter ) )
370 {
371 if ( max_iter <= 0 )
372 {
373 LOG( M_ERROR,
374 "SimulationManager::set_status",
375 "Maximal number of iterations for the waveform relaxation must be "
376 "positive. To disable waveform relaxation set use_wfr instead." );
377 throw KernelException();
378 }
379 else
380 {
381 wfr_max_iterations_ = max_iter;
382 }
383 }
384
385 // set the interpolation order for the waveform relaxation method
386 long interp_order;
387 if ( updateValue< long >( d, names::wfr_interpolation_order, interp_order ) )
388 {
389 if ( ( interp_order < 0 ) or ( interp_order == 2 ) or ( interp_order > 3 ) )
390 {
391 LOG( M_ERROR, "SimulationManager::set_status", "Interpolation order must be 0, 1, or 3." );
392 throw KernelException();
393 }
394 else
395 {
396 wfr_interpolation_order_ = interp_order;
397 }
398 }
399
400 // update time limit
401 double t_new = 0.0;
402 if ( updateValue< double >( d, names::update_time_limit, t_new ) )
403 {
404 if ( t_new <= 0 )
405 {
406 LOG( M_ERROR, "SimulationManager::set_status", "update_time_limit > 0 required." );
407 throw KernelException();
408 }
409
410 update_time_limit_ = t_new;
411 }
412 }
413
414 void
get_status(DictionaryDatum & d)415 nest::SimulationManager::get_status( DictionaryDatum& d )
416 {
417 def< double >( d, names::ms_per_tic, Time::get_ms_per_tic() );
418 def< double >( d, names::tics_per_ms, Time::get_tics_per_ms() );
419 def< long >( d, names::tics_per_step, Time::get_tics_per_step() );
420 def< double >( d, names::resolution, Time::get_resolution().get_ms() );
421
422 def< double >( d, names::T_min, Time::min().get_ms() );
423 def< double >( d, names::T_max, Time::max().get_ms() );
424
425 def< double >( d, names::biological_time, get_time().get_ms() );
426 def< long >( d, names::to_do, to_do_ );
427 def< bool >( d, names::print_time, print_time_ );
428
429 def< bool >( d, names::use_wfr, use_wfr_ );
430 def< double >( d, names::wfr_comm_interval, wfr_comm_interval_ );
431 def< double >( d, names::wfr_tol, wfr_tol_ );
432 def< long >( d, names::wfr_max_iterations, wfr_max_iterations_ );
433 def< long >( d, names::wfr_interpolation_order, wfr_interpolation_order_ );
434
435 def< double >( d, names::update_time_limit, update_time_limit_ );
436 def< double >( d, names::min_update_time, min_update_time_ );
437 def< double >( d, names::max_update_time, max_update_time_ );
438
439 def< double >( d, names::time_simulate, sw_simulate_.elapsed() );
440 def< double >( d, names::time_communicate_prepare, sw_communicate_prepare_.elapsed() );
441 #ifdef TIMER_DETAILED
442 def< double >( d, names::time_gather_spike_data, sw_gather_spike_data_.elapsed() );
443 def< double >( d, names::time_update, sw_update_.elapsed() );
444 def< double >( d, names::time_gather_target_data, sw_gather_target_data_.elapsed() );
445 #endif
446 }
447
448 void
prepare()449 nest::SimulationManager::prepare()
450 {
451 assert( kernel().is_initialized() );
452
453 if ( prepared_ )
454 {
455 std::string msg = "Prepare called twice.";
456 LOG( M_ERROR, "SimulationManager::prepare", msg );
457 throw KernelException();
458 }
459
460 if ( inconsistent_state_ )
461 {
462 throw KernelException(
463 "Kernel is in inconsistent state after an "
464 "earlier error. Please run ResetKernel first." );
465 }
466
467 // reset profiling timers
468 reset_timers_for_dynamics();
469 kernel().event_delivery_manager.reset_timers_for_dynamics();
470
471 t_real_ = 0;
472 t_slice_begin_ = timeval(); // set to timeval{0, 0} as unset flag
473 t_slice_end_ = timeval(); // set to timeval{0, 0} as unset flag
474
475 // find shortest and longest delay across all MPI processes
476 // this call sets the member variables
477 kernel().connection_manager.update_delay_extrema_();
478 kernel().event_delivery_manager.init_moduli();
479
480 // if at the beginning of a simulation, set up spike buffers
481 if ( not simulated_ )
482 {
483 kernel().event_delivery_manager.configure_spike_data_buffers();
484 }
485
486 kernel().node_manager.ensure_valid_thread_local_ids();
487 kernel().node_manager.prepare_nodes();
488
489 kernel().model_manager.create_secondary_events_prototypes();
490
491 // we have to do enter_runtime after prepare_nodes, since we use
492 // calibrate to map the ports of MUSIC devices, which has to be done
493 // before enter_runtime
494 if ( not simulated_ ) // only enter the runtime mode once
495 {
496 double tick = Time::get_resolution().get_ms() * kernel().connection_manager.get_min_delay();
497 kernel().music_manager.enter_runtime( tick );
498 }
499 prepared_ = true;
500
501 // check whether waveform relaxation is used on any MPI process;
502 // needs to be called before update_connection_intrastructure_since
503 // it resizes coefficient arrays for secondary events
504 kernel().node_manager.check_wfr_use();
505
506 if ( kernel().node_manager.have_nodes_changed() or kernel().connection_manager.connections_have_changed() )
507 {
508 #pragma omp parallel
509 {
510 const thread tid = kernel().vp_manager.get_thread_id();
511 update_connection_infrastructure( tid );
512 } // of omp parallel
513 }
514 }
515
516 void
assert_valid_simtime(Time const & t)517 nest::SimulationManager::assert_valid_simtime( Time const& t )
518 {
519 if ( t == Time::ms( 0.0 ) )
520 {
521 return;
522 }
523
524 if ( t < Time::step( 1 ) )
525 {
526 LOG( M_ERROR,
527 "SimulationManager::run",
528 String::compose( "Simulation time must be >= %1 ms (one time step).", Time::get_resolution().get_ms() ) );
529 throw KernelException();
530 }
531
532 if ( t.is_finite() )
533 {
534 Time time1 = clock_ + t;
535 if ( not time1.is_finite() )
536 {
537 std::string msg = String::compose(
538 "A clock overflow will occur after %1 of %2 ms. Please reset network "
539 "clock first!",
540 ( Time::max() - clock_ ).get_ms(),
541 t.get_ms() );
542 LOG( M_ERROR, "SimulationManager::run", msg );
543 throw KernelException();
544 }
545 }
546 else
547 {
548 std::string msg = String::compose(
549 "The requested simulation time exceeds the largest time NEST can handle "
550 "(T_max = %1 ms). Please use a shorter time!",
551 Time::max().get_ms() );
552 LOG( M_ERROR, "SimulationManager::run", msg );
553 throw KernelException();
554 }
555 }
556
557 void
run(Time const & t)558 nest::SimulationManager::run( Time const& t )
559 {
560 assert_valid_simtime( t );
561
562 kernel().random_manager.check_rng_synchrony();
563 kernel().io_manager.pre_run_hook();
564
565 if ( not prepared_ )
566 {
567 std::string msg = "Run called without calling Prepare.";
568 LOG( M_ERROR, "SimulationManager::run", msg );
569 throw KernelException();
570 }
571
572 to_do_ += t.get_steps();
573 to_do_total_ = to_do_;
574
575 if ( to_do_ == 0 )
576 {
577 return;
578 }
579
580 // Reset local spike counters within event_delivery_manager
581 kernel().event_delivery_manager.reset_counters();
582
583 sw_simulate_.start();
584
585 // from_step_ is not touched here. If we are at the beginning
586 // of a simulation, it has been reset properly elsewhere. If
587 // a simulation was ended and is now continued, from_step_ will
588 // have the proper value. to_step_ is set as in advance_time().
589
590 delay end_sim = from_step_ + to_do_;
591 if ( kernel().connection_manager.get_min_delay() < end_sim )
592 {
593 to_step_ = kernel().connection_manager.get_min_delay(); // update to end of time slice
594 }
595 else
596 {
597 to_step_ = end_sim; // update to end of simulation time
598 }
599
600 // Warn about possible inconsistencies, see #504.
601 // This test cannot come any earlier, because we first need to compute
602 // min_delay_
603 // above.
604 if ( t.get_steps() % kernel().connection_manager.get_min_delay() != 0 )
605 {
606 LOG( M_WARNING,
607 "SimulationManager::run",
608 "The requested simulation time is not an integer multiple of the minimal "
609 "delay in the network. This may result in inconsistent results under the "
610 "following conditions: (i) A network contains more than one source of "
611 "randomness, e.g., two different poisson_generators, and (ii) Simulate "
612 "is called repeatedly with simulation times that are not multiples of "
613 "the minimal delay." );
614 }
615
616 call_update_();
617
618 kernel().io_manager.post_run_hook();
619 kernel().random_manager.check_rng_synchrony();
620
621 sw_simulate_.stop();
622 }
623
624 void
cleanup()625 nest::SimulationManager::cleanup()
626 {
627 if ( not prepared_ )
628 {
629 std::string msg = "Cleanup called without calling Prepare.";
630 LOG( M_ERROR, "SimulationManager::cleanup", msg );
631 throw KernelException();
632 }
633
634 if ( not simulated_ )
635 {
636 prepared_ = false;
637 return;
638 }
639
640 kernel().node_manager.finalize_nodes();
641 prepared_ = false;
642 }
643
644 void
call_update_()645 nest::SimulationManager::call_update_()
646 {
647 assert( kernel().is_initialized() and not inconsistent_state_ );
648
649 std::ostringstream os;
650 double t_sim = to_do_ * Time::get_resolution().get_ms();
651
652 size_t num_active_nodes = kernel().node_manager.get_num_active_nodes();
653 os << "Number of local nodes: " << num_active_nodes << std::endl;
654 os << "Simulation time (ms): " << t_sim;
655
656 #ifdef _OPENMP
657 os << std::endl
658 << "Number of OpenMP threads: " << kernel().vp_manager.get_num_threads();
659 #else
660 os << std::endl
661 << "Not using OpenMP";
662 #endif
663
664 #ifdef HAVE_MPI
665 os << std::endl
666 << "Number of MPI processes: " << kernel().mpi_manager.get_num_processes();
667 #else
668 os << std::endl
669 << "Not using MPI";
670 #endif
671
672 LOG( M_INFO, "SimulationManager::start_updating_", os.str() );
673
674
675 if ( to_do_ == 0 )
676 {
677 return;
678 }
679
680 if ( print_time_ )
681 {
682 // TODO: Remove direct output
683 std::cout << std::endl;
684 print_progress_();
685 }
686
687 simulating_ = true;
688 simulated_ = true;
689
690 update_();
691
692 simulating_ = false;
693
694 if ( print_time_ )
695 {
696 std::cout << std::endl;
697 }
698
699 kernel().mpi_manager.synchronize();
700
701 LOG( M_INFO, "SimulationManager::run", "Simulation finished." );
702 }
703
704 void
update_connection_infrastructure(const thread tid)705 nest::SimulationManager::update_connection_infrastructure( const thread tid )
706 {
707 #pragma omp barrier
708 if ( tid == 0 )
709 {
710 sw_communicate_prepare_.start();
711 }
712
713 kernel().connection_manager.restructure_connection_tables( tid );
714 kernel().connection_manager.sort_connections( tid );
715 kernel().connection_manager.collect_compressed_spike_data( tid );
716
717 #pragma omp barrier // wait for all threads to finish sorting
718
719 #pragma omp single
720 {
721 kernel().connection_manager.compute_target_data_buffer_size();
722 kernel().event_delivery_manager.resize_send_recv_buffers_target_data();
723
724 // check whether primary and secondary connections exists on any
725 // compute node
726 kernel().connection_manager.sync_has_primary_connections();
727 kernel().connection_manager.check_secondary_connections_exist();
728 }
729
730 if ( kernel().connection_manager.secondary_connections_exist() )
731 {
732 #pragma omp barrier
733 kernel().connection_manager.compute_compressed_secondary_recv_buffer_positions( tid );
734 #pragma omp barrier
735 #pragma omp single
736 {
737 kernel().mpi_manager.communicate_recv_counts_secondary_events();
738 kernel().event_delivery_manager.configure_secondary_buffers();
739 }
740 }
741
742 #ifdef TIMER_DETAILED
743 if ( tid == 0 )
744 {
745 sw_gather_target_data_.start();
746 }
747 #endif
748
749 // communicate connection information from postsynaptic to
750 // presynaptic side
751 kernel().event_delivery_manager.gather_target_data( tid );
752
753 #ifdef TIMER_DETAILED
754 #pragma omp barrier
755 if ( tid == 0 )
756 {
757 sw_gather_target_data_.stop();
758 }
759 #endif
760
761 if ( kernel().connection_manager.secondary_connections_exist() )
762 {
763 kernel().connection_manager.compress_secondary_send_buffer_pos( tid );
764 }
765
766 #pragma omp barrier
767 if ( kernel().connection_manager.use_compressed_spikes() )
768 {
769 kernel().connection_manager.clear_compressed_spike_data_map( tid );
770 }
771
772 #pragma omp single
773 {
774 kernel().node_manager.set_have_nodes_changed( false );
775 kernel().connection_manager.unset_connections_have_changed();
776 }
777
778 #pragma omp barrier
779 if ( tid == 0 )
780 {
781 sw_communicate_prepare_.stop();
782 }
783 }
784
785 bool
wfr_update_(Node * n)786 nest::SimulationManager::wfr_update_( Node* n )
787 {
788 return ( n->wfr_update( clock_, from_step_, to_step_ ) );
789 }
790
791 void
update_()792 nest::SimulationManager::update_()
793 {
794 // to store done values of the different threads
795 std::vector< bool > done;
796 bool done_all = true;
797 delay old_to_step;
798
799 double start_current_update = sw_simulate_.elapsed();
800 bool update_time_limit_exceeded = false;
801
802 std::vector< std::shared_ptr< WrappedThreadException > > exceptions_raised( kernel().vp_manager.get_num_threads() );
803 // parallel section begins
804 #pragma omp parallel
805 {
806 const thread tid = kernel().vp_manager.get_thread_id();
807
808 do
809 {
810 if ( print_time_ )
811 {
812 gettimeofday( &t_slice_begin_, NULL );
813 }
814
815 if ( kernel().sp_manager.is_structural_plasticity_enabled()
816 and ( std::fmod( Time( Time::step( clock_.get_steps() + from_step_ ) ).get_ms(),
817 kernel().sp_manager.get_structural_plasticity_update_interval() ) == 0 ) )
818 {
819 for ( SparseNodeArray::const_iterator i = kernel().node_manager.get_local_nodes( tid ).begin();
820 i != kernel().node_manager.get_local_nodes( tid ).end();
821 ++i )
822 {
823 Node* node = i->get_node();
824 node->update_synaptic_elements( Time( Time::step( clock_.get_steps() + from_step_ ) ).get_ms() );
825 }
826 #pragma omp barrier
827 #pragma omp single
828 {
829 kernel().sp_manager.update_structural_plasticity();
830 }
831 // Remove 10% of the vacant elements
832 for ( SparseNodeArray::const_iterator i = kernel().node_manager.get_local_nodes( tid ).begin();
833 i != kernel().node_manager.get_local_nodes( tid ).end();
834 ++i )
835 {
836 Node* node = i->get_node();
837 node->decay_synaptic_elements_vacant();
838 }
839
840 // after structural plasticity has created and deleted
841 // connections, update the connection infrastructure; implies
842 // complete removal of presynaptic part and reconstruction
843 // from postsynaptic data
844 update_connection_infrastructure( tid );
845
846 } // of structural plasticity
847
848 if ( from_step_ == 0 )
849 {
850 #ifdef HAVE_MUSIC
851 // advance the time of music by one step (min_delay * h) must
852 // be done after deliver_events_() since it calls
853 // music_event_out_proxy::handle(), which hands the spikes over to
854 // MUSIC *before* MUSIC time is advanced
855
856 // wait until all threads are done -> synchronize
857 #pragma omp barrier
858 // the following block is executed by the master thread only
859 // the other threads are enforced to wait at the end of the block
860 #pragma omp master
861 {
862 // advance the time of music by one step (min_delay * h) must
863 // be done after deliver_events_() since it calls
864 // music_event_out_proxy::handle(), which hands the spikes over to
865 // MUSIC *before* MUSIC time is advanced
866 if ( slice_ > 0 )
867 {
868 kernel().music_manager.advance_music_time();
869 }
870
871 // the following could be made thread-safe
872 kernel().music_manager.update_music_event_handlers( clock_, from_step_, to_step_ );
873 }
874 // end of master section, all threads have to synchronize at this point
875 #pragma omp barrier
876 #endif
877 }
878
879 // preliminary update of nodes that use waveform relaxtion, only
880 // necessary if secondary connections exist and any node uses
881 // wfr
882 if ( kernel().connection_manager.secondary_connections_exist() and kernel().node_manager.wfr_is_used() )
883 {
884 #pragma omp single
885 {
886 // if the end of the simulation is in the middle
887 // of a min_delay_ step, we need to make a complete
888 // step in the wfr_update and only do
889 // the partial step in the final update
890 // needs to be done in omp single since to_step_ is a scheduler
891 // variable
892 old_to_step = to_step_;
893 if ( to_step_ < kernel().connection_manager.get_min_delay() )
894 {
895 to_step_ = kernel().connection_manager.get_min_delay();
896 }
897 }
898
899 bool max_iterations_reached = true;
900 const std::vector< Node* >& thread_local_wfr_nodes = kernel().node_manager.get_wfr_nodes_on_thread( tid );
901 for ( long n = 0; n < wfr_max_iterations_; ++n )
902 {
903 bool done_p = true;
904
905 // this loop may be empty for those threads
906 // that do not have any nodes requiring wfr_update
907 for ( std::vector< Node* >::const_iterator i = thread_local_wfr_nodes.begin();
908 i != thread_local_wfr_nodes.end();
909 ++i )
910 {
911 done_p = wfr_update_( *i ) and done_p;
912 }
913
914 // add done value of thread p to done vector
915 #pragma omp critical
916 done.push_back( done_p );
917 // parallel section ends, wait until all threads are done -> synchronize
918 #pragma omp barrier
919
920 // the following block is executed by a single thread
921 // the other threads wait at the end of the block
922 #pragma omp single
923 {
924 // check whether all threads are done
925 for ( size_t i = 0; i < done.size(); ++i )
926 {
927 done_all = done[ i ] and done_all;
928 }
929
930 // gather SecondaryEvents (e.g. GapJunctionEvents)
931 kernel().event_delivery_manager.gather_secondary_events( done_all );
932
933 // reset done and done_all
934 //(needs to be in the single threaded part)
935 done_all = true;
936 done.clear();
937 }
938
939 // deliver SecondaryEvents generated during wfr_update
940 // returns the done value over all threads
941 done_p = kernel().event_delivery_manager.deliver_secondary_events( tid, true );
942
943 if ( done_p )
944 {
945 max_iterations_reached = false;
946 break;
947 }
948 } // of for (wfr_max_iterations) ...
949
950 #pragma omp single
951 {
952 to_step_ = old_to_step;
953 if ( max_iterations_reached )
954 {
955 std::string msg = String::compose( "Maximum number of iterations reached at interval %1-%2 ms",
956 clock_.get_ms(),
957 clock_.get_ms() + to_step_ * Time::get_resolution().get_ms() );
958 LOG( M_WARNING, "SimulationManager::wfr_update", msg );
959 }
960 }
961
962 } // of if(wfr_is_used)
963 // end of preliminary update
964
965 #ifdef TIMER_DETAILED
966 #pragma omp barrier
967 if ( tid == 0 )
968 {
969 sw_update_.start();
970 }
971 #endif
972 const SparseNodeArray& thread_local_nodes = kernel().node_manager.get_local_nodes( tid );
973
974 for ( SparseNodeArray::const_iterator n = thread_local_nodes.begin(); n != thread_local_nodes.end(); ++n )
975 {
976 // We update in a parallel region. Therefore, we need to catch
977 // exceptions here and then handle them after the parallel region.
978 try
979 {
980 Node* node = n->get_node();
981 if ( not( node )->is_frozen() )
982 {
983 ( node )->update( clock_, from_step_, to_step_ );
984 }
985 }
986 catch ( std::exception& e )
987 {
988 // so throw the exception after parallel region
989 exceptions_raised.at( tid ) = std::shared_ptr< WrappedThreadException >( new WrappedThreadException( e ) );
990 }
991 }
992
993 // parallel section ends, wait until all threads are done -> synchronize
994 #pragma omp barrier
995 #ifdef TIMER_DETAILED
996 if ( tid == 0 )
997 {
998 sw_update_.stop();
999 sw_gather_spike_data_.start();
1000 }
1001 #endif
1002
1003 // gather and deliver only at end of slice, i.e., end of min_delay step
1004 if ( to_step_ == kernel().connection_manager.get_min_delay() )
1005 {
1006 if ( kernel().connection_manager.has_primary_connections() )
1007 {
1008 kernel().event_delivery_manager.gather_spike_data( tid );
1009 }
1010 if ( kernel().connection_manager.secondary_connections_exist() )
1011 {
1012 #pragma omp single
1013 {
1014 kernel().event_delivery_manager.gather_secondary_events( true );
1015 }
1016 kernel().event_delivery_manager.deliver_secondary_events( tid, false );
1017 }
1018 }
1019
1020 #pragma omp barrier
1021 #ifdef TIMER_DETAILED
1022 if ( tid == 0 )
1023 {
1024 sw_gather_spike_data_.stop();
1025 }
1026 #endif
1027
1028 // the following block is executed by the master thread only
1029 // the other threads are enforced to wait at the end of the block
1030 #pragma omp master
1031 {
1032 advance_time_();
1033
1034 if ( print_time_ )
1035 {
1036 gettimeofday( &t_slice_end_, NULL );
1037 print_progress_();
1038 }
1039
1040 // We cannot throw exception inside master, would not get caught.
1041 const double end_current_update = sw_simulate_.elapsed();
1042 const double update_time = end_current_update - start_current_update;
1043 update_time_limit_exceeded = update_time > update_time_limit_;
1044 min_update_time_ = std::min( min_update_time_, update_time );
1045 max_update_time_ = std::max( max_update_time_, update_time );
1046 start_current_update = end_current_update;
1047 }
1048 // end of master section, all threads have to synchronize at this point
1049 #pragma omp barrier
1050 kernel().io_manager.post_step_hook();
1051 // enforce synchronization after post-step activities of the recording backends
1052 #pragma omp barrier
1053 const double end_current_update = sw_simulate_.elapsed();
1054 if ( end_current_update - start_current_update > update_time_limit_ )
1055 {
1056 LOG( M_ERROR, "SimulationManager::update", "Update time limit exceeded." );
1057 throw KernelException();
1058 }
1059 start_current_update = end_current_update;
1060
1061 } while ( to_do_ > 0 and not update_time_limit_exceeded and not exceptions_raised.at( tid ) );
1062
1063 // End of the slice, we update the number of synaptic elements
1064 for ( SparseNodeArray::const_iterator i = kernel().node_manager.get_local_nodes( tid ).begin();
1065 i != kernel().node_manager.get_local_nodes( tid ).end();
1066 ++i )
1067 {
1068 Node* node = i->get_node();
1069 node->update_synaptic_elements( Time( Time::step( clock_.get_steps() + to_step_ ) ).get_ms() );
1070 }
1071
1072 } // of omp parallel
1073
1074 if ( update_time_limit_exceeded )
1075 {
1076 LOG( M_ERROR, "SimulationManager::update", "Update time limit exceeded." );
1077 throw KernelException();
1078 }
1079
1080 // check if any exceptions have been raised
1081 for ( thread tid = 0; tid < kernel().vp_manager.get_num_threads(); ++tid )
1082 {
1083 if ( exceptions_raised.at( tid ).get() )
1084 {
1085 simulating_ = false; // must mark this here, see #311
1086 inconsistent_state_ = true;
1087 throw WrappedThreadException( *( exceptions_raised.at( tid ) ) );
1088 }
1089 }
1090 }
1091
1092 void
advance_time_()1093 nest::SimulationManager::advance_time_()
1094 {
1095 // time now advanced time by the duration of the previous step
1096 to_do_ -= to_step_ - from_step_;
1097
1098 // advance clock, update modulos, slice counter only if slice completed
1099 if ( ( delay ) to_step_ == kernel().connection_manager.get_min_delay() )
1100 {
1101 clock_ += Time::step( kernel().connection_manager.get_min_delay() );
1102 ++slice_;
1103 kernel().event_delivery_manager.update_moduli();
1104 from_step_ = 0;
1105 }
1106 else
1107 {
1108 from_step_ = to_step_;
1109 }
1110
1111 long end_sim = from_step_ + to_do_;
1112
1113 if ( kernel().connection_manager.get_min_delay() < ( delay ) end_sim )
1114 {
1115 // update to end of time slice
1116 to_step_ = kernel().connection_manager.get_min_delay();
1117 }
1118 else
1119 {
1120 to_step_ = end_sim; // update to end of simulation time
1121 }
1122
1123 assert( to_step_ - from_step_ <= ( long ) kernel().connection_manager.get_min_delay() );
1124 }
1125
1126 void
print_progress_()1127 nest::SimulationManager::print_progress_()
1128 {
1129 double rt_factor = 0.0;
1130
1131 if ( t_slice_end_.tv_sec != 0 )
1132 {
1133 // usec
1134 long t_real_s = ( t_slice_end_.tv_sec - t_slice_begin_.tv_sec ) * 1e6;
1135 // usec
1136 t_real_ += t_real_s + ( t_slice_end_.tv_usec - t_slice_begin_.tv_usec );
1137 // ms
1138 double t_real_acc = ( t_real_ ) / 1000.;
1139 double t_sim_acc = ( to_do_total_ - to_do_ ) * Time::get_resolution().get_ms();
1140 // real-time factor = wall-clock time / model time
1141 rt_factor = t_real_acc / t_sim_acc;
1142 }
1143
1144 int percentage = ( 100 - int( float( to_do_ ) / to_do_total_ * 100 ) );
1145
1146 std::cout << "\r[ " << std::setw( 3 ) << std::right << percentage << "% ] "
1147 << "Model time: " << std::fixed << std::setprecision( 1 ) << clock_.get_ms() << " ms, "
1148 << "Real-time factor: " << std::setprecision( 4 ) << rt_factor
1149 << std::resetiosflags( std::ios_base::floatfield );
1150 std::flush( std::cout );
1151 }
1152
1153 nest::Time const
get_previous_slice_origin() const1154 nest::SimulationManager::get_previous_slice_origin() const
1155 {
1156 return clock_ - Time::step( kernel().connection_manager.get_min_delay() );
1157 }
1158