Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Connections better use typedefed types Segment, Synapse, ... #331

Merged
merged 57 commits into from
Apr 6, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
3244350
SP: remove round5_() as not needed
breznak Mar 16, 2019
c6b3696
SP: globa inh: optimization
breznak Mar 17, 2019
a5f4b13
Connections: updateSynapsePermanence optimization
breznak Mar 17, 2019
09b6f51
Connections::updateSynapsePermanence optimization
breznak Mar 17, 2019
4df1210
Revert "Connections: updateSynapsePermanence optimization"
breznak Mar 17, 2019
ca6cee2
VectorHelpers: union, sparse_cellsToColumns use template T
breznak Mar 17, 2019
6be5eb3
Connections: use typedefs Synapse, Segment
breznak Mar 17, 2019
9535b56
Revert "Revert "Connections: updateSynapsePermanence optimization""
breznak Mar 17, 2019
7b17674
Revert "Connections::updateSynapsePermanence optimization"
breznak Mar 17, 2019
b8199bd
Connections, SP, TM: use typedefs from Connections
breznak Mar 17, 2019
def0898
Connections: use smaller datatypes WIP
breznak Mar 18, 2019
858df3b
Connections::load fix max value
breznak Mar 19, 2019
aa84db2
Connections::load simplify, support only version 2
breznak Mar 19, 2019
27511f0
Connections: add check for data-type overflow
breznak Mar 19, 2019
f88416e
Merge branch 'master_community' into connections_opt
breznak Mar 19, 2019
bf56929
add debug info
breznak Mar 19, 2019
ac9bfb4
Connections: fix check comparison
breznak Mar 21, 2019
57e4e27
TM: replace isSortedWithoutDuplicates with is_sorted
breznak Mar 21, 2019
c45e85f
TM: sorted SDR indices for activateCells
breznak Mar 21, 2019
ad9cbea
ConnectionsPerformanceTest: cleanup and use SDRs
breznak Mar 21, 2019
3b59e36
ConnectionsPerformanceTest: remove testTP
breznak Mar 21, 2019
5537fa2
Connections: fixing data-type overflow checks
breznak Mar 21, 2019
3a389ad
ConnectionsPerformanceTest: use default SP params
breznak Mar 21, 2019
99a20ff
Connections: fix type for removeSynapseFromPreSynapticMap_
breznak Mar 21, 2019
3a89a7c
TM: use typedefs from Connections
breznak Mar 21, 2019
0bfd866
Merge branch 'master_community' into connections_opt
breznak Mar 21, 2019
3a724ed
fix bindings
breznak Mar 21, 2019
3439dc3
SP: debugging ExactOutput test
breznak Mar 21, 2019
558af1c
Merge branch 'master_community' into connections_opt
breznak Mar 25, 2019
c8ee571
WIP disable failing SP test
breznak Mar 25, 2019
80bd126
COnnections: return to original datatypes
breznak Mar 26, 2019
e0e98c4
Merge branch 'master_community' into connections_opt
breznak Apr 2, 2019
d55af21
TM: remove irrelevant test
breznak Apr 2, 2019
c37d74a
COnnections: use using instead of typedef
breznak Apr 2, 2019
3216f54
review feedback
breznak Apr 2, 2019
ba248fa
Connections: fix createSegment/Synapse overflow
breznak Apr 3, 2019
533242f
TM bindings: use typedefs from Connections
breznak Apr 3, 2019
3f849e7
Connections: add createSegment test for overflow
breznak Apr 4, 2019
27a7d81
COnnections: test createSegments overflow runtime skip
breznak Apr 4, 2019
493e308
Connections: add test for createSynapse overflow
breznak Apr 4, 2019
d02eb76
TMRegion: use typedef connections::CellIdx
breznak Apr 4, 2019
ccda59c
Connections: use size_t
breznak Apr 4, 2019
c034ca3
TM: growSynapses: cleanup & adapt to size_t from Connections
breznak Apr 4, 2019
6609451
small fixups for Connections type changes
breznak Apr 4, 2019
e87166e
Connections: improve operator==
breznak Apr 4, 2019
c1499f7
TM: adapt to size_t changes from Connections
breznak Apr 4, 2019
132d706
Merge branch 'master_community' into connections_opt
breznak Apr 4, 2019
d27d9ce
TM small fix
breznak Apr 4, 2019
ecb5584
SDR: use using for typedef
breznak Apr 4, 2019
fa9e70d
SDR: add typedefs for ElemSparse, ElemDense
breznak Apr 4, 2019
d37ede8
COnnections: bind CellIdx with sdr::ElemSparse
breznak Apr 4, 2019
069ba3c
SdrTools: fixes for change-able SDR::ElemDense
breznak Apr 4, 2019
db49a59
fix typo in Debug assert
breznak Apr 4, 2019
7c5921b
Merge branch 'master_community' into connections_opt
breznak Apr 4, 2019
90169f7
Merge branch 'master_community' into connections_opt
breznak Apr 5, 2019
c46e4c4
review feedback
breznak Apr 5, 2019
7cbe5b5
feedback 2
breznak Apr 5, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 17 additions & 14 deletions bindings/py/cpp_src/bindings/algorithms/py_HTM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ namespace nupic_ext
namespace py = pybind11;
using namespace nupic;
using nupic::sdr::SDR;
using nupic::algorithms::connections::Permanence;
using namespace nupic::algorithms::connections;

void init_HTM(py::module& m)
{
Expand All @@ -53,14 +53,21 @@ using nupic::algorithms::connections::Permanence;
py::class_<HTM_t> py_HTM(m, "TemporalMemory");

py_HTM.def(py::init<>());
py_HTM.def(py::init<std::vector<UInt>
, UInt, UInt
, Permanence, Permanence
, UInt, UInt
, Permanence, Permanence, Permanence
py_HTM.def(py::init<std::vector<CellIdx>
, CellIdx
, SynapseIdx
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bindings too now use proper typedefs

, Permanence
, Permanence
, SynapseIdx
, SynapseIdx
, Permanence
, Permanence
, Permanence
, Int
, UInt, UInt
, bool, UInt>()
, SegmentIdx
, SynapseIdx
, bool
, UInt>()
, py::arg("columnDimensions")
, py::arg("cellsPerColumn") = 32
, py::arg("activationThreshold") = 13
Expand Down Expand Up @@ -151,16 +158,12 @@ using nupic::algorithms::connections::Permanence;

py_HTM.def("getActiveSegments", [](const HTM_t& self)
{
auto activeSegments = self.getActiveSegments();

return py::array_t<nupic::UInt32>(activeSegments.size(), activeSegments.data());
return self.getActiveSegments();
});

py_HTM.def("getMatchingSegments", [](const HTM_t& self)
{
auto matchingSegments = self.getMatchingSegments();

return py::array_t<nupic::UInt32>(matchingSegments.size(), matchingSegments.data());
return self.getMatchingSegments();
});

py_HTM.def("cellsForColumn", [](HTM_t& self, UInt columnIdx)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ namespace nupic_ext
{
auto overlaps = self.getOverlaps();

return py::array_t<UInt>( overlaps.size(), overlaps.data());
return py::array_t<SynapseIdx>( overlaps.size(), overlaps.data());
});

// getBoostedOverlaps
Expand Down
110 changes: 38 additions & 72 deletions src/nupic/algorithms/Connections.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,13 @@ void Connections::unsubscribe(UInt32 token) {

Segment Connections::createSegment(CellIdx cell) {
Segment segment;
if (destroyedSegments_.size() > 0) {
if (!destroyedSegments_.empty() ) { //reuse old, destroyed segs
segment = destroyedSegments_.back();
destroyedSegments_.pop_back();
} else {
segment = (Segment)segments_.size();
} else { //create a new segment
NTA_CHECK(segments_.size() < std::numeric_limits<Segment>::max()) << "Add segment failed: Range of Segment (data-type) insufficinet size."
<< (size_t)segments_.size() << " < " << (size_t)std::numeric_limits<Segment>::max();
segment = static_cast<Segment>(segments_.size());
segments_.push_back(SegmentData());
ctrl-z-9000-times marked this conversation as resolved.
Show resolved Hide resolved
segmentOrdinals_.push_back(0);
}
Expand All @@ -112,11 +114,13 @@ Synapse Connections::createSynapse(Segment segment,
Permanence permanence) {
// Get an index into the synapses_ list, for the new synapse to reside at.
Synapse synapse;
if (destroyedSynapses_.size() > 0) {
if (!destroyedSynapses_.empty() ) {
synapse = destroyedSynapses_.back();
destroyedSynapses_.pop_back();
} else {
synapse = (UInt)synapses_.size();
NTA_CHECK(synapses_.size() < std::numeric_limits<Synapse>::max()) << "Add synapse failed: Range of Synapse (data-type) insufficient size."
<< synapses_.size() << " < " << (size_t)std::numeric_limits<Synapse>::max();
synapse = static_cast<Synapse>(synapses_.size());
synapses_.push_back(SynapseData());
synapseOrdinals_.push_back(0);
}
Expand Down Expand Up @@ -166,7 +170,7 @@ bool Connections::synapseExists_(Synapse synapse) const {
* last synapse in the list over this synapse.
*/
void Connections::removeSynapseFromPresynapticMap_(
const UInt index,
const Synapse index,
vector<Synapse> &preSynapses,
vector<Segment> &preSegments)
{
Expand Down Expand Up @@ -267,19 +271,23 @@ void Connections::updateSynapsePermanence(Synapse synapse,
permanence = std::max(permanence, minPermanence );

auto &synData = synapses_[synapse];
bool before = synData.permanence >= connectedThreshold_;
bool after = permanence >= connectedThreshold_;

const bool before = synData.permanence >= connectedThreshold_;
const bool after = permanence >= connectedThreshold_;
synData.permanence = permanence;

if( before != after ) {
if( before == after ) { //no change
return;
}
const auto &presyn = synData.presynapticCell;
auto &potentialPresyn = potentialSynapsesForPresynapticCell_[presyn];
auto &potentialPreseg = potentialSegmentsForPresynapticCell_[presyn];
auto &connectedPresyn = connectedSynapsesForPresynapticCell_[presyn];
auto &connectedPreseg = connectedSegmentsForPresynapticCell_[presyn];
const auto &segment = synData.segment;
auto &segmentData = segments_[segment];
if( after ) {

if( after ) { //connect
segmentData.numConnected++;

// Remove this synapse from presynaptic potential synapses.
Expand All @@ -291,7 +299,7 @@ void Connections::updateSynapsePermanence(Synapse synapse,
connectedPresyn.push_back( synapse );
connectedPreseg.push_back( segment );
}
else {
else { //disconnected
segmentData.numConnected--;

// Remove this synapse from presynaptic connected synapses.
Expand All @@ -304,10 +312,9 @@ void Connections::updateSynapsePermanence(Synapse synapse,
potentialPreseg.push_back( segment );
}

for (auto h : eventHandlers_) {
for (auto h : eventHandlers_) { //TODO handle callbacks in performance-critical method only in Debug?
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this method is a hotspot I found in profiling, do we really need the callbacks here, can be left out only for debug,.. ?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea I have no idea why these exist but their part of the public API so I didn't remove them.
Maybe try: for( const auto & : eventHandlers_) for speed?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll profile w/o the loop, imo this would be a candidate to break the API, if shows performance gain.

h.second->onUpdateSynapsePermanence(synapse, permanence);
}
}
}

const vector<Segment> &Connections::segmentsForCell(CellIdx cell) const {
Expand Down Expand Up @@ -358,9 +365,7 @@ const SynapseData &Connections::dataForSynapse(Synapse synapse) const {
return synapses_[synapse];
}

UInt32 Connections::segmentFlatListLength() const { return (UInt32)segments_.size(); }

bool Connections::compareSegments(Segment a, Segment b) const {
bool Connections::compareSegments(const Segment a, const Segment b) const {
const SegmentData &aData = segments_[a];
const SegmentData &bData = segments_[b];
if (aData.cell < bData.cell) {
Expand All @@ -385,24 +390,24 @@ Connections::synapsesForPresynapticCell(CellIdx presynapticCell) const {


void Connections::computeActivity(
vector<UInt32> &numActiveConnectedSynapsesForSegment,
vector<SynapseIdx> &numActiveConnectedSynapsesForSegment,
const vector<CellIdx> &activePresynapticCells) const
{
NTA_ASSERT(numActiveConnectedSynapsesForSegment.size() == segments_.size());

// Iterate through all connected synapses.
for (CellIdx cell : activePresynapticCells) {
for (const auto& cell : activePresynapticCells) {
if (connectedSegmentsForPresynapticCell_.count(cell)) {
for( Segment segment : connectedSegmentsForPresynapticCell_.at(cell)) {
for(const auto& segment : connectedSegmentsForPresynapticCell_.at(cell)) {
++numActiveConnectedSynapsesForSegment[segment];
}
}
}
}

void Connections::computeActivity(
vector<UInt32> &numActiveConnectedSynapsesForSegment,
vector<UInt32> &numActivePotentialSynapsesForSegment,
vector<SynapseIdx> &numActiveConnectedSynapsesForSegment,
vector<SynapseIdx> &numActivePotentialSynapsesForSegment,
const vector<CellIdx> &activePresynapticCells) const {
NTA_ASSERT(numActiveConnectedSynapsesForSegment.size() == segments_.size());
NTA_ASSERT(numActivePotentialSynapsesForSegment.size() == segments_.size());
Expand All @@ -416,9 +421,9 @@ void Connections::computeActivity(
std::copy( numActiveConnectedSynapsesForSegment.begin(),
numActiveConnectedSynapsesForSegment.end(),
numActivePotentialSynapsesForSegment.begin());
for (CellIdx cell : activePresynapticCells) {
for (const auto& cell : activePresynapticCells) {
if (potentialSegmentsForPresynapticCell_.count(cell)) {
for( Segment segment : potentialSegmentsForPresynapticCell_.at(cell)) {
for(const auto& segment : potentialSegmentsForPresynapticCell_.at(cell)) {
++numActivePotentialSynapsesForSegment[segment];
}
}
Expand Down Expand Up @@ -502,7 +507,7 @@ void Connections::raisePermanencesToThreshold(

// Raise the permance of all synapses in the potential pool uniformly.
for( const auto &syn : synapses ) //TODO vectorize: vector + const to all members
updateSynapsePermanence(syn, synapses_[syn].permanence + increment);
updateSynapsePermanence(syn, synapses_[syn].permanence + increment); //this is performance HOTSPOT
}


Expand Down Expand Up @@ -561,7 +566,7 @@ void Connections::load(std::istream &inStream) {
// Check the saved version.
int version;
inStream >> version;
NTA_CHECK(version <= 2);
NTA_CHECK(version == 2);

// Retrieve simple variables
UInt numCells;
Expand All @@ -570,22 +575,13 @@ void Connections::load(std::istream &inStream) {
inStream >> connectedThreshold;
initialize(numCells, connectedThreshold);

// This logic is complicated by the fact that old versions of the Connections
// serialized "destroyed" segments and synapses, which we now ignore.
for (UInt cell = 0; cell < numCells; cell++) {

UInt numSegments;
inStream >> numSegments;

for (SegmentIdx j = 0; j < numSegments; j++) {
bool destroyedSegment = false;
if (version < 2) {
inStream >> destroyedSegment;
}

Segment segment = {(UInt32)-1};
if (!destroyedSegment)
segment = createSegment( cell );
Segment segment = createSegment( cell );

UInt numSynapses;
inStream >> numSynapses;
Expand All @@ -596,15 +592,6 @@ void Connections::load(std::istream &inStream) {
inStream >> presyn;
inStream >> perm;

if (version < 2) {
bool destroyedSynapse = false;
inStream >> destroyedSynapse;
if( destroyedSynapse )
continue;
}
if( destroyedSegment )
continue;

createSynapse( segment, presyn, perm );
}
}
Expand All @@ -615,51 +602,33 @@ void Connections::load(std::istream &inStream) {
}


CellIdx Connections::numCells() const { return (CellIdx)cells_.size(); }

UInt Connections::numSegments() const {
return (UInt)(segments_.size() - destroyedSegments_.size());
}

UInt Connections::numSegments(CellIdx cell) const {
return (UInt)cells_[cell].segments.size();
}

UInt Connections::numSynapses() const {
return (UInt)(synapses_.size() - destroyedSynapses_.size());
}

UInt Connections::numSynapses(Segment segment) const {
return (UInt)segments_[segment].synapses.size();
}

bool Connections::operator==(const Connections &other) const {
if (cells_.size() != other.cells_.size())
return false;

for (CellIdx i = 0; i < cells_.size(); ++i) {
for (CellIdx i = 0; i < static_cast<CellIdx>(cells_.size()); i++) {
const CellData &cellData = cells_[i];
const CellData &otherCellData = other.cells_[i];

if (cellData.segments.size() != otherCellData.segments.size()) {
return false;
}

for (SegmentIdx j = 0; j < (SegmentIdx)cellData.segments.size(); ++j) {
Segment segment = cellData.segments[j];
for (SegmentIdx j = 0; j < static_cast<SegmentIdx>(cellData.segments.size()); j++) {
const Segment segment = cellData.segments[j];
const SegmentData &segmentData = segments_[segment];
Segment otherSegment = otherCellData.segments[j];
const Segment otherSegment = otherCellData.segments[j];
const SegmentData &otherSegmentData = other.segments_[otherSegment];

if (segmentData.synapses.size() != otherSegmentData.synapses.size() ||
segmentData.cell != otherSegmentData.cell) {
return false;
}

for (SynapseIdx k = 0; k < (SynapseIdx)segmentData.synapses.size(); ++k) {
Synapse synapse = segmentData.synapses[k];
for (SynapseIdx k = 0; k < static_cast<SynapseIdx>(segmentData.synapses.size()); k++) {
const Synapse synapse = segmentData.synapses[k];
const SynapseData &synapseData = synapses_[synapse];
Synapse otherSynapse = otherSegmentData.synapses[k];
const Synapse otherSynapse = otherSegmentData.synapses[k];
const SynapseData &otherSynapseData = other.synapses_[otherSynapse];

if (synapseData.presynapticCell != otherSynapseData.presynapticCell ||
Expand All @@ -677,6 +646,3 @@ bool Connections::operator==(const Connections &other) const {
return true;
}

bool Connections::operator!=(const Connections &other) const {
return !(*this == other);
}
Loading