/** \fn content(po::variables_map const& vm) \brief Execute the NEST synapse Miniapp. \param vm encapsulate the command line and all needed informations */ void model_content(po::variables_map const& vm, subpragram& subprog) { int nSpikes = vm["nSpikes"].as<int>(); bool use_connection = subprog == connection; bool use_connector = subprog == connector; bool use_manager = subprog == manager; bool use_mpi = subprog == distributed; if (use_mpi) { std::stringstream command; std::string path = helper_build_path::mpi_bin_path(); size_t nthread = vm["nThreads"].as<int>(); std::string mpi_run = vm["run"].as<std::string>(); size_t nproc = vm["nProcesses"].as<int>(); //command line args size_t ncells = vm["nNeurons"].as<int>(); size_t fan = vm["fanout"].as<int>(); size_t mindelay = vm["min_delay"].as<int>(); size_t simtime = vm["simtime"].as<int>(); double rate = vm["rate"].as<double>(); if (rate>=0) { nSpikes = rate * ncells * simtime; std::cout << "WARNING: nSpikes is overwritten by rate. new value of nSpikes=" << nSpikes << std::endl; } std::string syn_model = vm["model"].as<std::string>(); double syn_delay = vm["delay"].as<double>(); double syn_weight = vm["weight"].as<double>(); double syn_U = vm["U"].as<double>(); double syn_u = vm["u"].as<double>(); double syn_x = vm["x"].as<double>(); double syn_tau_rec = vm["tau_rec"].as<double>(); double syn_tau_fac = vm["tau_fac"].as<double>(); bool pool = vm["pool"].as<bool>(); std::string exec ="nest_dist_exec"; command << "OMP_NUM_THREADS=" << nthread << " " << mpi_run <<" -n "<< nproc << " " << path << exec << " " << nthread << " " << simtime << " " << ncells << " " << fan << " " << nSpikes << " " << mindelay << " " << syn_model << " " << syn_delay << " " << syn_weight << " " << syn_U << " " << syn_u << " " << syn_x << " " << syn_tau_rec << " " << syn_tau_fac << " " << pool; std::cout<< "Running command " << command.str() <<std::endl; system(command.str().c_str()); return; } boost::chrono::system_clock::duration delay; if ( use_manager ) { const bool pool = vm["pool"].as<bool>(); const int thrd = vm["thread"].as<int>(); // thead_num const int min_delay=vm["min_delay"].as<int>(); const int simtime = vm["simtime"].as<int>(); const int nthreads = vm["nThreads"].as<int>(); const int rank = vm["rank"].as<int>(); const int size = vm["nProcesses"].as<int>(); const int ncells = vm["nNeurons"].as<int>(); const int fanout = vm["fanout"].as<int>(); //setup allocator nest::pool_env penv(nthreads, pool); //build connection manager connectionmanager cm(vm); environment::continousdistribution neuro_dist(size, rank, ncells); environment::presyn_maker presyns(fanout, environment::fixedoutdegree); presyns(thrd, &neuro_dist); //preallocate vector for results std::vector<spikedetector> detectors(ncells); std::vector<targetindex> detectors_targetindex(ncells); // register spike detectors for(unsigned int i=0; i < ncells; ++i) { detectors[i].set_lid(i); //give nodes a local id //scheduler stores pointers to the spike detectors detectors_targetindex[i] = scheduler::add_node(&detectors[i]); //add them to the scheduler } environment::continousdistribution neuro_vp_dist(nthreads, thrd, &neuro_dist); build_connections_from_neuron(thrd, neuro_vp_dist, presyns, detectors_targetindex, cm); // generate all events for one thread environment::event_generator generator(1); double mean = static_cast<double>(simtime) / static_cast<double>(nSpikes); double lambda = 1.0 / static_cast<double>(mean * size); //all events available environment::continousdistribution event_dist(1, 0, ncells); environment::generate_poisson_events(generator.begin(), simtime, nthreads, rank, size, lambda, &event_dist); const unsigned int stats_generated_spikes = generator.get_size(0); int t = 0; spikeevent se; boost::chrono::system_clock::time_point start = boost::chrono::system_clock::now(); while (t<simtime) { t+=min_delay; // get events from all threads while(generator.compare_top_lte(0, t)) { environment::gen_event g = generator.pop(0); index nid = g.first; se.set_stamp( Time(g.second) ); // in Network::send< SpikeEvent > se.set_sender_gid( nid ); // in Network::send< SpikeEvent > cm.send(thrd, nid, se); //send spike } } delay = boost::chrono::system_clock::now() - start; std::cout << "Connection manager simulated" << std::endl; std::cout << "Statistics:" << std::endl; std::cout << "\tgenerated spikes: " << stats_generated_spikes << std::endl; int recvSpikes=0; for (unsigned int i=0; i<detectors.size(); i++) recvSpikes+=detectors[i].spikes.size(); std::cout << "\trecv spikes: " << recvSpikes << std::endl; std::cout << "\tEvents left:" << std::endl; while (!generator.empty(0)) { // thread 0 environment::gen_event g = generator.pop(0); // thread 0 std::cout << "Event " << g.first << " " << g.second << std::endl; } } else if ( use_connector ) { const bool pool = vm["pool"].as<bool>(); const double syn_delay = vm["delay"].as<double>(); const double syn_weight = vm["weight"].as<double>(); const double syn_U = vm["U"].as<double>(); const double syn_u = vm["u"].as<double>(); const double syn_x = vm["x"].as<double>(); const double syn_tau_rec = vm["tau_rec"].as<double>(); const double syn_tau_fac = vm["tau_fac"].as<double>(); const int fanout = vm["fanout"].as<int>(); //setup allocator nest::pool_env penv(1, pool); // use one thread //preallocate vector for results std::vector<spikedetector> detectors(fanout); std::vector<targetindex> detectors_targetindex(fanout); for(unsigned int i=0; i < fanout; ++i) { detectors[i].set_lid(i); //give nodes a local id //scheduler stores pointers to the spike detectors detectors_targetindex[i] = scheduler::add_node(&detectors[i]); //add them to the scheduler } //create connector ptr //has to be set to NULL (check add_connection(..)) ConnectorBase* conn = NULL; //build connector for(unsigned int i=0; i < fanout; ++i) { //TODO permute parameters tsodyks2 synapse(syn_delay, syn_weight, syn_U, syn_u, syn_x, syn_tau_rec, syn_tau_fac, detectors_targetindex[i%fanout]); conn = add_connection(conn, synapse); //use static function from connectionmanager } //create a few events std::vector< spikeevent > events(nSpikes); for (unsigned int i=0; i<nSpikes; i++) { Time t(i*10.0); events[i].set_stamp( t ); // in Network::send< SpikeEvent > events[i].set_sender( NULL ); // in Network::send< SpikeEvent > } boost::chrono::system_clock::time_point start = boost::chrono::system_clock::now(); for (unsigned int i=0; i<nSpikes; i++) { conn->send(events[i]); //send spike } delay = boost::chrono::system_clock::now() - start; std::cout << "Connector simulated with " << fanout << " connections" << std::endl; } else { const double syn_delay = vm["delay"].as<double>(); const double syn_weight = vm["weight"].as<double>(); const double syn_U = vm["U"].as<double>(); const double syn_u = vm["u"].as<double>(); const double syn_x = vm["x"].as<double>(); const double syn_tau_rec = vm["tau_rec"].as<double>(); const double syn_tau_fac = vm["tau_fac"].as<double>(); //preallocate vector for results spikedetector detector; // register spike detectors targetindex detector_targetindex = scheduler::add_node(&detector); //add them to the scheduler tsodyks2 syn(syn_delay, syn_weight, syn_U, syn_u, syn_x, syn_tau_rec, syn_tau_fac, detector_targetindex); //create a few events std::vector< spikeevent > events(nSpikes); for (unsigned int i=0; i<nSpikes; i++) { Time t(i*10.0); events[i].set_stamp( t ); // in Network::send< SpikeEvent > events[i].set_sender( NULL ); // in Network::send< SpikeEvent > } double t_lastspike = 0.0; boost::chrono::system_clock::time_point start = boost::chrono::system_clock::now(); for (unsigned int i=0; i<nSpikes; i++) { syn.send(events[i], t_lastspike); //send spike t_lastspike += 0.2; // dt - time between spiks } delay = boost::chrono::system_clock::now() - start; std::cout << "Single connection simulated" << std::endl; std::cout << "Last weight " << detector.spikes.back().get_weight() << std::endl; } std::cout << "Duration: " << delay << std::endl; }
/** \fn content(po::variables_map const& vm) \brief Execute the NEST synapse Miniapp. \param vm encapsulate the command line and all needed informations */ void model_content(po::variables_map const& vm) { PoorMansAllocator poormansallocpool; double dt = vm["dt"].as<double>(); int iterations = vm["iterations"].as<int>(); const int num_connections = vm["nConnections"].as<int>(); const int num_detectors = vm["nDetectors"].as<int>(); bool with_connector = vm.count("connector") > 0; bool with_manager = vm.count("manager") > 0; //will turn into ptr to base class if more synapse are implemented tsodyks2* syn; ConnectorBase* conn = NULL; //preallocate vector for results std::vector<spikedetector> detectors(num_detectors); std::vector<targetindex> detectors_targetindex(num_detectors); // register spike detectors connectionmanager* cn = NULL; for(unsigned int i=0; i < num_detectors; ++i) { detectors[i].set_lid(i); //give nodes a local id //scheduler stores pointers to the spike detectors detectors_targetindex[i] = scheduler::add_node(&detectors[i]); //add them to the scheduler } if (vm["model"].as<std::string>() == "tsodyks2") { const double delay = vm["delay"].as<double>(); const double weight = vm["weight"].as<double>(); const double U = vm["U"].as<double>(); const double u = vm["u"].as<double>(); const double x = vm["x"].as<double>(); const double tau_rec = vm["tau_rec"].as<double>(); const double tau_fac = vm["tau_fac"].as<double>(); const bool pool = vm["pool"].as<bool>(); if(pool){ poormansallocpool.states = pool; } if ( with_manager ) { //build connection manager cn = new connectionmanager(vm); build_connections_from_neuron(detectors_targetindex, *cn, vm); } else if ( with_connector ) { //build connector for(unsigned int i=0; i < num_connections; ++i) { //TODO permute parameters tsodyks2 synapse(delay, weight, U, u, x, tau_rec, tau_fac, detectors_targetindex[i%num_detectors]); conn = add_connection(conn, synapse); //use static function from connectionmanager } } else { syn = new tsodyks2(delay, weight, U, u, x, tau_rec, tau_fac, detectors_targetindex[0]); } } /* else if () .. further synapse models*/ else { throw std::invalid_argument("connection model implementation missing"); } //create a few events std::vector< spikeevent > events(iterations); for (unsigned int i=0; i<iterations; i++) { Time t(i*10.0); events[i].set_stamp( t ); // in Network::send< SpikeEvent > events[i].set_sender( NULL ); // in Network::send< SpikeEvent > //events[i]->set_sender_gid( sgid ); // Network::send_local } boost::chrono::system_clock::duration delay; if ( with_manager ) { if (cn==NULL) { throw std::runtime_error("connectionmanager pointer is not valid"); } const int t = vm["thread"].as<int>(); // thead_num const int min_delay=vm["min_delay"].as<int>(); const int nSpikes = vm["nSpikes"].as<int>(); const int simtime = iterations * min_delay; const int ngroups = vm["nGroups"].as<int>(); const int rank = vm["rank"].as<int>(); const int size = vm["size"].as<int>(); const int ncells = vm["nNeurons"].as<int>(); //environment::event_generator generator(nSpikes, simtime, ngroups, rank, size, ncells); environment::event_generator generator(ngroups); double mean = static_cast<double>(simtime) / static_cast<double>(nSpikes); double lambda = 1.0 / static_cast<double>(mean * size); environment::generate_poisson_events(generator.begin(), simtime, ngroups, rank, size, ncells, lambda); const unsigned int stats_generated_spikes = generator.get_size(t); int sim_time = 0; spikeevent se; boost::chrono::system_clock::time_point start = boost::chrono::system_clock::now(); for (unsigned int i=0; i<iterations; i++) { sim_time+=min_delay; while(generator.compare_top_lte(t, sim_time)) { environment::gen_event g = generator.pop(t); index nid = g.first; se.set_stamp( Time(g.second) ); // in Network::send< SpikeEvent > se.set_sender_gid( nid ); // in Network::send< SpikeEvent > cn->send(t, nid, se); //send spike } } delay = boost::chrono::system_clock::now() - start; std::cout << "Connection manager simulated" << std::endl; std::cout << "Statistics:" << std::endl; std::cout << "\tgenerated spikes: " << stats_generated_spikes << std::endl; int recvSpikes=0; for (unsigned int i=0; i<detectors.size(); i++) recvSpikes+=detectors[i].spikes.size(); std::cout << "\trecv spikes: " << recvSpikes << std::endl; std::cout << "\tEvents left:" << std::endl; while (!generator.empty(t)) { environment::gen_event g = generator.pop(t); std::cout << "Event " << g.first << " " << g.second << std::endl; } delete cn; } else if ( with_connector ) { if (conn==NULL) { throw std::runtime_error("connector pointer is not valid"); } boost::chrono::system_clock::time_point start = boost::chrono::system_clock::now(); for (unsigned int i=0; i<iterations; i++) { conn->send(events[i]); //send spike } delay = boost::chrono::system_clock::now() - start; std::cout << "Connector simulated with " << num_connections << " connections" << std::endl; } else { if (!syn) { throw std::runtime_error("connection pointer is not valid"); } double t_lastspike = 0.0; boost::chrono::system_clock::time_point start = boost::chrono::system_clock::now(); for (unsigned int i=0; i<iterations; i++) { syn->send(events[i], t_lastspike); //send spike t_lastspike += dt; } delay = boost::chrono::system_clock::now() - start; std::cout << "Single connection simulated" << std::endl; delete syn; } std::cout << "Duration: " << delay << std::endl; std::cout << "Last weight " << detectors[0].spikes.back().get_weight() << std::endl; }