/* * \fn build_connections_from_neuron(std::vector<targetindex>& detectors_targetindex, connectionmanager& cn, po::variables_map const& vm) * \brief build connections in connection manager using generator from coreneuron miniapp * \param detectors_targetindex vector of targetindexes to target nodes * \param cn reference to connection manager * \param vm refrence to boost variables map */ void build_connections_from_neuron(std::vector<targetindex>& detectors_targetindex, connectionmanager& cm, po::variables_map const& vm) { const int size = vm["size"].as<int>(); //get all connections for all nodes const int rank = vm["rank"].as<int>(); const int t = vm["thread"].as<int>(); // thread_num const int ngroups = vm["nGroups"].as<int>(); //one thread available const int fan = vm["nConnections"].as<int>(); const int ncells = vm["nNeurons"].as<int>(); //environment::event_generator generator(nSpikes, simtime, ngroups, rank, size, ncells); environment::presyn_maker presyns(ncells, fan, environment::fixedoutdegree); presyns(size, ngroups, rank); for (unsigned int s_gid=0; s_gid<ncells; s_gid++) { const environment::presyn* local_synapses = presyns.find_output(s_gid); if(local_synapses != NULL) { for(int i = 0; i<local_synapses->size(); ++i){ const unsigned int t_gid = (*local_synapses)[i]; //sort out locally stored connections const unsigned int dest = t_gid % (ngroups * size); if(dest == t) { //local id out of global id const unsigned int t_lid = t_gid / (ngroups * size); targetindex target = detectors_targetindex[t_lid%detectors_targetindex.size()]; cm.connect(t, s_gid, target); } } } const environment::presyn* global_synapses = presyns.find_input(s_gid); if(global_synapses != NULL) { for(int i = 0; i<global_synapses->size(); ++i){ const unsigned int t_gid = (*global_synapses)[i]; //sort out locally stored connections const unsigned int dest = t_gid % (ngroups * size); if(dest == t) { //local id out of global id const unsigned int t_lid = t_gid / (ngroups * size); targetindex target = detectors_targetindex[t_lid%detectors_targetindex.size()]; cm.connect(t, s_gid, target); } } } } }
int main(int argc, char* argv[]) { assert(argc == 8); MPI_Init(NULL, NULL); MPI_Datatype mpi_spike = create_spike_type(); int rank, size; MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &size); int ngroups = atoi(argv[1]); int simtime = atoi(argv[2]); int ncells = atoi(argv[3]); int fanin = atoi(argv[4]); int nSpikes = atoi(argv[5]); int mindelay = atoi(argv[6]); bool algebra = atoi(argv[7]); struct timeval start, end; int cellsper = ncells / size; //create environment 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::continousdistribution neuro_dist(size, rank, ncells); environment::generate_events_kai(generator.begin(), simtime, ngroups, rank, size, lambda, &neuro_dist); environment::presyn_maker presyns(fanin); presyns(rank, &neuro_dist); spike::spike_interface s_interface(size); //run simulation MPI_Comm neighborhood = create_dist_graph(presyns, cellsper); queueing::pool pl(algebra, ngroups, mindelay, rank, s_interface); gettimeofday(&start, NULL); while(pl.get_time() <= simtime){ pl.fixed_step(generator, presyns); distributed_spike(s_interface, mpi_spike, neighborhood); pl.filter(presyns); } gettimeofday(&end, NULL); long long diff_ms = (1000 * (end.tv_sec - start.tv_sec)) + ((end.tv_usec - start.tv_usec) / 1000); if(rank == 0){ std::cout<<"run time: "<<diff_ms<<" ms"<<std::endl; } pl.accumulate_stats(); accumulate_stats(s_interface); MPI_Comm_free(&neighborhood); MPI_Type_free(&mpi_spike); MPI_Finalize(); return 0; }
/** \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; }