📄 network.cpp
字号:
/*************************************************************************** Network.cpp - description ------------------- copyright : (C) 2001, 2004 by Matt Grover email : mgrover@amygdala.org ***************************************************************************//*************************************************************************** * * * This program 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. * * * ***************************************************************************/#include <amygdala/network.h>#include <amygdala/spikingneuron.h>#include <amygdala/inputneuron.h>#include <amygdala/spikeinput.h>#include <amygdala/netloader.h>#include <amygdala/utilities.h>#include <amygdala/amygdalaclass.h>#include <amygdala/logging.h>#include <amygdala/visualstub.h>#include "amygdala/axon.h"#include "amygdala/axonnode.h"#include "amygdala/synapse.h"#include "amygdala/functionlookup.h"#include "amygdala/trainer.h"#include <iostream>#include <stdlib.h>#include <time.h>#include <pthread.h>#include <unistd.h>#include <stdexcept>#include <sys/stat.h>#include <sys/types.h>#ifdef HAVE_CONFIG_H#include <config.h>#endifusing namespace std;using namespace Amygdala;// Callback function for the pthread library/*extern "C" { void* NetworkThread(void* ){ LOGGER(1, "Starting new thread"); Network *Network = Network::GetNetworkRef(); Network->Schedule(); return new int(0); }}*/// to enable profiling threads on Linux.// This code is shamelessly stolen from Samuel Hocevar. Thanks#ifdef PROFILING#include <sys/time.h>/*extern "C" { typedef struct wrapper_s { void * (*start_routine)(void *); void * arg; pthread_mutex_t lock; pthread_cond_t wait; struct itimerval itimer; } wrapper_t; static void * wrapper_routine(void *); int gprof_pthread_create(pthread_t * thread, pthread_attr_t * attr, void * (*start_routine)(void *), void * arg) { wrapper_t wrapper_data; int i_return; wrapper_data.start_routine = start_routine; wrapper_data.arg = arg; getitimer(ITIMER_PROF, &wrapper_data.itimer); pthread_cond_init(&wrapper_data.wait, NULL); pthread_mutex_init(&wrapper_data.lock, NULL); pthread_mutex_lock(&wrapper_data.lock); i_return = pthread_create(thread, attr, &wrapper_routine, &wrapper_data); if(i_return == 0) { pthread_cond_wait(&wrapper_data.wait, &wrapper_data.lock); } pthread_mutex_unlock(&wrapper_data.lock); pthread_mutex_destroy(&wrapper_data.lock); pthread_cond_destroy(&wrapper_data.wait); return i_return; } static void * wrapper_routine(void * data) { void * (*start_routine)(void *) = ((wrapper_t*)data)->start_routine; void * arg = ((wrapper_t*)data)->arg; setitimer(ITIMER_PROF, &((wrapper_t*)data)->itimer, NULL); pthread_mutex_lock(&((wrapper_t*)data)->lock); pthread_cond_signal(&((wrapper_t*)data)->wait); pthread_mutex_unlock(&((wrapper_t*)data)->lock); return NetworkThread(arg); }}*/#endif // PROFILING//////////////////////////////////////////////////////////////////Network * Network::theNetwork = NULL;AmTimeInt Network::simTime = 0;AmIdInt Network::nextNeuronId = 1;AmTimeInt Network::simStepSize = 100;Network::Network(int & argc, char * argv[]){ srand(time(0)); numThreads = 1; running = false; bool visualize = false; for(int i=0; i<argc; i++) { if(strstr(argv[i], "--visual")){ visualize = true; // no stripping of the --visual argument here - Visual strips it } } if(visualize) { visualStub = new VisualStub(); try { visualStub->Init(argc, argv); } catch (runtime_error e) { cerr << e.what() << endl; delete visualStub; visualStub = NULL; } } else { visualStub=0; } funcLookup = new FunctionLookup(); eventRequestCount = 0; maxSpikeDelay = 0; currSpikeDelayOffset = 0; maxOffset = 0; spikeBatchCount = 0;}void Network::Cleanup(){ delete theNetwork;}Network::~Network(){ delete funcLookup;}void Network::ShiftArgs(int pos, int & argc, char *argv[]){ if(pos == argc) return; // was the last arg for(int i=pos+1; i<argc; i++) { argv[i-1] = argv[i]; } argc--;}void Network::Stop(){ maxRunTime = simTime;}void Network::Run(AmTimeInt _maxRunTime){ running = true; maxRunTime = _maxRunTime; if (simTime == 0) { throw runtime_error("Network::InitRun() must be called before Network::Run()"); } if(visualStub) { visualStub->RunVisual(); } while(simTime < maxRunTime){ // This will eventually be supplemented with multithreading code. TimeStep(); } // NOTE:Threading code commented out until single-threaded mode is working again. // Much of this will have to change because partitions will not be used, but // some of it may be useful, so I have left it here. /*sleepers = 0; pthread_mutex_init(&mut_sleeper, NULL); pthread_mutex_init(&mut_simtime, NULL); pthread_cond_init(&cond_sleeper, NULL); if(numThreads == 1){ // no worker thread cout << "Running partitioned network, no threading" << endl; Schedule(); // to facilitate debugging running = false; return; }*/ /*for(unsigned int threadCount = 0; threadCount < numThreads; threadCount++){ pthread_t *theThread = new pthread_t; threadHandles.push_back(theThread);#ifdef PROFILING gprof_pthread_create (theThread, NULL, NetworkThread, NULL);#else pthread_create (theThread, NULL, NetworkThread, NULL);#endif LOGGER(1, "Amygdala thread " << threadCount << " runnning "); }*/ /*for(unsigned int threadCount = 0; threadCount < numThreads; threadCount++){ int *retval; pthread_t *theThread = threadHandles[threadCount]; pthread_join (*theThread, (void**)&retval); LOGGER(1, "Amygdala thread " << threadCount << " exited with status " << *retval) delete theThread; delete retval; } threadHandles.clear();*/ running = false;}void Network::TimeStep(){ LOGGER(4, "Network executing a timestep at time " << simTime) while (!eventQ.empty()) { const SpikeRequest& topSpike = eventQ.top(); if (topSpike.spikeTime != simTime) break; topSpike.requestor->SendSpike(simTime); eventQ.pop(); } // get the next input for (unsigned int i=0; i<spikeInputVec.size(); ++i) { LOGGER(6, "Reading spike input buffer") spikeInputVec[i]->ReadInputBuffer(); } if (!inputQ.empty()) { nextInputTime = inputQ.top().spikeTime; LOGGER(6, "Setting nextInputTime " << nextInputTime) } else { nextInputTime = 0; } while (nextInputTime <= simTime) { if (nextInputTime == 0) break; LOGGER(5, "Preparing to send input spike") inputQ.top().requestor->SendInputSpike(simTime); inputQ.pop(); if (!inputQ.empty()) { nextInputTime = inputQ.top().spikeTime; } else { nextInputTime = 0; } } SendDelayedSpikes(); // callbacks to any Trainers that are queued up if (!trainerCallbackQ.empty()) { AmTimeInt callTime = trainerCallbackQ.top().callbackTime; while (callTime <= simTime) { trainerCallbackQ.top().trainer->PeriodicTrain(); trainerCallbackQ.pop(); if (trainerCallbackQ.empty()) { break; } callTime = trainerCallbackQ.top().callbackTime; } } simTime += TimeStepSize();}void Network::InitRun(){ if (simTime == 0) simTime = TimeStepSize(); // Initialize the topology objects map<std::string, Topology*>::iterator itr; for (itr=topologyMap.begin(); itr != topologyMap.end(); itr++) { itr->second->InitRun(); } // Initialize the delayed spike queue if it has not been done. if (!delayedSpikeQ.size()) { InitializeDelayedSpikeQ(); } if (!inputQ.empty()) { nextInputTime = inputQ.top().spikeTime; } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -