// Mutate synapses. void NetworkHomomorph::mutate() { int i, j, k, n; float weight; Synapse *synapse; i = randomNeuron(true); n = network->numNeurons; for (j = 0; j < n; j++) { weight = (float)randomizer->RAND_INTERVAL( synapseWeightsParm.minimum, synapseWeightsParm.maximum); for (k = 0; k < (int)network->synapses[i][j].size(); k++) { synapse = network->synapses[i][j][k]; synapse->setWeight(weight); } } }
int run(boost::mpi::environment& env, boost::scoped_ptr<nemo::Network>& net, unsigned ncount, unsigned scount, unsigned duration, unsigned nType, unsigned mType, const char* outfile, const char* configFile, const char* logDir) { boost::mpi::communicator world; boost::filesystem::path logDirPath(logDir); boost::filesystem::create_directory(logDirPath); std::ostringstream simDir; simDir << logDir << "/simulation-p" << world.size() << "-n" << ncount << "-s" << scount << "-nt" << nType << "-mt" << mType; boost::filesystem::path simDirPath(simDir.str()); boost::filesystem::create_directory(simDirPath); try { if ( world.rank() == nemo::mpi::MASTER ) { nemo::Configuration conf(world.rank(), configFile); std::cout << "Constructing master..." << std::endl; nemo::mpi::Master master(env, world, *net, mType, conf, logDir); std::ostringstream filename; filename << simDir.str() << "/" << outfile; std::ofstream file(filename.str().c_str()); rng_t rng; uirng_t randomNeuron(rng, boost::uniform_int<>(0, ncount - 1)); master.resetTimer(); nemo::Simulation::firing_stimulus firingStimulus(10); for ( unsigned ms = 0; ms < duration; ++ms ) { for ( unsigned i = 0; i < 10; i++ ) firingStimulus[i] = randomNeuron(); master.step(firingStimulus); const std::vector<unsigned>& firing = master.readFiring(); file << ms << ": "; std::copy(firing.begin(), firing.end(), std::ostream_iterator<unsigned>(file, " ")); file << std::endl; } std::ostringstream oss; oss << "Simulated " << master.elapsedSimulation() << " ms wall clock time: " << master.elapsedWallclock() << "ms" << std::endl; std::cout << oss.str() << std::endl; /* Write general stats to simulation folder */ filename.str(""); filename.clear(); filename << simDir.str() << "/general-stats.txt"; writeStats(filename.str().c_str(), scount, master.elapsedSimulation(), master.elapsedWallclock(), *net, conf); master.appendMpiStats(filename.str().c_str()); /* Write firing counters to simulation folder */ filename.str(""); filename.clear(); filename << simDir.str() << "/firing-counters.txt"; master.writeFiringCounters(filename.str().c_str()); } else { std::cout << "Starting worker " << world.rank() << "..." << std::endl; nemo::Configuration conf(world.rank(), configFile); if ( conf.stdpEnabled() ) { std::cout << "STDP enabled" << std::endl; setStandardStdpFunction(conf); } nemo::mpi::runWorker(env, world, conf, simDir.str().c_str()); } } catch (nemo::exception& e) { std::cerr << world.rank() << ":" << e.what() << std::endl; env.abort(e.errorNumber()); } catch (boost::mpi::exception& e) { std::cerr << world.rank() << ": " << e.what() << std::endl; env.abort(-1); } return 0; }
// Initialize synapse optimization. void NetworkHomomorph::initOptimize(vector<vector<Synapse *> >& synapses, vector<vector<float> >& permutations, int synapseOptimizedPathLength) { int i, j, k, n, p, q, s; bool forward; float weight; vector<pair<int, int> > visited; Synapse *synapse; vector<Synapse *> chemSynapses, elecSynapses; vector<vector<float> > weightRanges; vector<float> weightRange; vector<float> permutation; synapses.clear(); permutations.clear(); // Randomly select starting neuron with synapse. i = randomNeuron(); n = network->numNeurons; for (s = 0; s < n; s++) { if (i < network->numSensors) { forward = true; } else if ((i >= network->numSensors) && (i < (network->numSensors + network->numMotors))) { forward = false; } else { forward = randomizer->RAND_BOOL(); } if (forward) { for (j = 0; j < n; j++) { if (network->synapses[i][j].size() > 0) { break; } } if (j < n) { break; } } else { for (j = 0; j < n; j++) { if (network->synapses[j][i].size() > 0) { break; } } if (j < n) { break; } } i++; i = (i % n); } if (s == n) { return; } // Select synapse path. for (j = 0; j < synapseOptimizedPathLength; j++) { k = randomizer->RAND_CHOICE(n); for (s = 0; s < n; s++) { if (forward) { if (network->synapses[i][k].size() > 0) { for (p = 0, q = (int)visited.size(); p < q; p++) { if ((visited[p].first == i) && (visited[p].second == k)) { break; } } if (p == q) { visited.push_back(pair<int, int>(i, k)); chemSynapses.clear(); elecSynapses.clear(); for (p = 0, q = (int)network->synapses[i][k].size(); p < q; p++) { synapse = network->synapses[i][k][p]; if (synapse->type == Synapse::CHEMICAL) { chemSynapses.push_back(synapse); } else { elecSynapses.push_back(synapse); } } if (chemSynapses.size() > 0) { synapses.push_back(chemSynapses); } if (elecSynapses.size() > 0) { synapses.push_back(elecSynapses); } if ((chemSynapses.size() > 0) || (elecSynapses.size() > 0)) { i = k; break; } } } } else { if (network->synapses[k][i].size() > 0) { for (p = 0, q = (int)visited.size(); p < q; p++) { if ((visited[p].first == k) && (visited[p].second == i)) { break; } } if (p == q) { visited.push_back(pair<int, int>(k, i)); chemSynapses.clear(); elecSynapses.clear(); for (p = 0, q = (int)network->synapses[k][i].size(); p < q; p++) { synapse = network->synapses[k][i][p]; if (synapse->type == Synapse::CHEMICAL) { chemSynapses.push_back(synapse); } else { elecSynapses.push_back(synapse); } } if (chemSynapses.size() > 0) { synapses.push_back(chemSynapses); } if (elecSynapses.size() > 0) { synapses.push_back(elecSynapses); } if ((chemSynapses.size() > 0) || (elecSynapses.size() > 0)) { i = k; break; } } } } k++; k = (k % n); } if (s == n) { break; } } if (synapses.size() == 0) { return; } // Compose synapse weight permutations. for (i = 0, j = (int)synapses.size(); i < j; i++) { weightRange.clear(); weight = synapses[i][0]->weight; weightRange.push_back(weight); if (synapseWeightsParm.maxDelta > 0.0f) { weight = synapses[i][0]->weight - (float)randomizer->RAND_INTERVAL(0.0f, synapseWeightsParm.maxDelta); if (weight < synapseWeightsParm.minimum) { weight = synapseWeightsParm.minimum; } } weightRange.push_back(weight); if (synapseWeightsParm.maxDelta > 0.0f) { weight = synapses[i][0]->weight + (float)randomizer->RAND_INTERVAL(0.0f, synapseWeightsParm.maxDelta); if (weight > synapseWeightsParm.maximum) { weight = synapseWeightsParm.maximum; } } weightRange.push_back(weight); weightRanges.push_back(weightRange); } permutation.resize((int)synapses.size()); permuteWeights(weightRanges, permutations, permutation, 0, (int)synapses.size() - 1); }
long benchmark(nemo::Simulation* sim, unsigned n, unsigned m, boost::program_options::variables_map& vm, unsigned seconds) { unsigned stdpPeriod = vm["stdp-period"].as<unsigned>(); float stdpReward = vm["stdp-reward"].as<float>(); bool csv = vm.count("csv") != 0; bool verbose = !csv; bool provideFiringStimulus = vm.count("fstim") != 0; bool provideCurrentStimulus = vm.count("istim") != 0; bool vprobe = vm.count("vprobe") != 0; const unsigned MS_PER_SECOND = 1000; rng_t rng; uirng_t randomNeuron(rng, boost::uniform_int<>(0, n-1)); sim->resetTimer(); unsigned t = 0; float v = 0; /* Run for a few seconds to warm up the network */ if(verbose) std::cout << "Running simulation (warming up)..."; for(unsigned s=0; s < 5; ++s) { for(unsigned ms = 0; ms < MS_PER_SECOND; ++ms, ++t) { sim->step(); if(stdpPeriod && t % stdpPeriod == 0) { sim->applyStdp(stdpReward); } } } if(verbose) std::cout << "[" << sim->elapsedWallclock() << "ms elapsed]"; sim->resetTimer(); if(verbose) { std::cout << std::endl; std::cout << "Running simulation (gathering performance data)..."; } nemo::Simulation::firing_stimulus firingStimulus; nemo::Simulation::current_stimulus currentStimulus; unsigned long nfired = 0; for(unsigned s=0; s < seconds; ++s) { if(verbose) std::cout << s << " "; for(unsigned ms=0; ms<1000; ++ms, ++t) { if(provideFiringStimulus) { firingStimulus.resize(1); firingStimulus[0] = randomNeuron(); } if(provideCurrentStimulus) { currentStimulus.resize(1); currentStimulus[0] = std::make_pair(randomNeuron(), 0.001f); } const std::vector<unsigned>& fired = sim->step(firingStimulus, currentStimulus); nfired += fired.size(); if(vprobe) { /* Just read a single value. The whole neuron population will be synced */ v = sim->getMembranePotential(0); } if(stdpPeriod && t % stdpPeriod == 0) { sim->applyStdp(stdpReward); } } } long int elapsedWallclock = sim->elapsedWallclock(); if(verbose) std::cout << "[" << elapsedWallclock << "ms elapsed]"; if(verbose) std::cout << std::endl; unsigned long narrivals = nfired * m; double f = (double(nfired) / n) / double(seconds); /* Throughput is measured in terms of the number of spike arrivals per * wall-clock second */ unsigned long throughput = MS_PER_SECOND * narrivals / elapsedWallclock; double speedup = double(seconds*MS_PER_SECOND)/elapsedWallclock; if(verbose) { std::cout << "Total firings: " << nfired << std::endl; std::cout << "Avg. firing rate: " << f << "Hz\n"; std::cout << "Spike arrivals: " << narrivals << std::endl; std::cout << "Approx. throughput: " << throughput/1000000 << "Ma/s (million spike arrivals per second)\n"; std::cout << "Speedup wrt real-time: " << speedup << std::endl; } if(csv) { std::string sep = ", "; // raw data std::cout << n << sep << m << sep << seconds*MS_PER_SECOND << sep << elapsedWallclock << sep << stdpPeriod << sep << nfired; // derived data. Not strictly needed, at least if out-degree is fixed. std::cout << sep << narrivals << sep << f << sep << speedup << sep << throughput/1000000 << std::endl; } return elapsedWallclock; }