-
Notifications
You must be signed in to change notification settings - Fork 74
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
SpatialPooler cleanup #108
Conversation
breznak
commented
Nov 14, 2018
•
edited
edited
- cleanup SP code
- add lots of const qualifiers
- add asserts and checks to get/setters
- some optimizations
replaces with VectorHelpers.binaryToSparse()
removed definition of round(), must be provided in c++11
- add many ASSERTs - made const methods & params everywhere possible - some code cleanup,optimization
for serialization
Restarting stuck CI |
- fix deactivation value to 0 - document mutual exclusion (mutex) with numActivePerInhArea - MAX_LOCALAREADENSITY explains 0.5 value
as it is unused and explained some comments for cleanup
@dkeeney please review, SP cleanup& optimization |
why is it not initialized in initialize()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please review
mostly optimization & cleanups.
Please take a look at the mystery with synPermMax on OSX
bool operator<=(const Synapse &other) const = delete; | ||
bool operator<(const Synapse &other) const = delete; | ||
bool operator>=(const Synapse &other) const = delete; | ||
bool operator>(const Synapse &other) const = delete; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unrelated to this PR, I just did it when I was there :P
|
||
void boostOverlaps_(vector<UInt> &overlaps, vector<Real> &boostedOverlaps); | ||
void boostOverlaps_(const vector<UInt> &overlaps, vector<Real> &boostedOverlaps) const; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
making this much const seemed for better optimization, roughly 10-20% faster here
Real synPermMin_; | ||
Real synPermMax_; | ||
Real synPermMin_ = 0.0; | ||
Real synPermMax_ = 1.0; //TODO set in initialize(), somehow OSX does not set that?! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dkeeney can you explain this? It's later set in initialize()
, Linux OK, but OSX fails w/o this
@@ -1578,8 +1581,9 @@ TEST(SpatialPoolerTest, testInitPermConnected) { | |||
|
|||
TEST(SpatialPoolerTest, testInitPermNonConnected) { | |||
SpatialPooler sp; | |||
EXPECT_TRUE(sp.getSynPermMax() == 1.0) << sp.getSynPermMax(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
simple test to debug the synPermMax on OSX, it gave ~0.0
@@ -416,7 +427,7 @@ void SpatialPooler::initialize( | |||
synPermMin_ = 0.0; | |||
synPermMax_ = 1.0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it should have been set here!!
@@ -1183,7 +1192,7 @@ void SpatialPooler::load(istream &inStream) { | |||
// Check the saved version. | |||
UInt version; | |||
inStream >> version; | |||
NTA_CHECK(version <= version_); | |||
NTA_CHECK(version == version_); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, you are not going to be backward compatible with the previous version? I guess that is reasonable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good spot! Yeah.. here it would be possible to support the old format, but I've decided to prefer clean,small codebase (not many people actually relying on our code now) Do you agree with the removal?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding range checks for values is a good idea.
There should be lots of opportunities for cleanup here.
Suggest changing all Real's to Real32 so we lock in the size. Same with Int and UInt. For those places where size matters. use size_t (or Size) as type for values that deal with things returned from various size() functions. What we want to do is avoid automatic type conversions.
In many cases these are actually SDR arrays so they should be perhaps Byte arrays but maybe that would be going too far for now.
As long as you are in there, everywhere that there are numeric literals, add an 'f' or 'u' as appropriate for the data type. i.e. 0.05f This will save me the trouble of doing this later. MSVC complains if there is a type mismatch with literals. I also saw places where a literal was cast to a Real; just use the 'f'.
I saw you added a lot of auto's. That is good in that it allows the compiler to optimize more. I personally don't like using auto because I cannot see what the type is but that is just me.
Overall, good job.
Is there a way to just turn off appveyor for now? |
is this an advantage? Would sb want to run on Real(64)?
Too far. My plan is to separate into smaller pieces in #92 and then focus on the common SDR-type #109
Will do!
Yeah, it's person to person, I like it just for that reason, that I don't usually know the type exactly :) Thanks, will do the suggested changes and merge. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some thoughts about the type conversions, what do you think?
// force small data types | ||
using Real = Real32; | ||
using UInt = UInt32; | ||
using Int = Int32; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How is this useful on per file basis? I think the idea of Real
was exactly to avoid type conversions, so the whole codebase would use Real (etc) and then in one file you set Real = Real32
for all the code. Isn't that what you want?
Using Real64/32 is only for explicit cases.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, in Types.hpp all Real's are set to Real32. (Unless you set double precision)
But it is not obvious looking at the code how big it is. I personally would like to see Real32 everywhere....or even "float" for floating point numbers.
There are reasons for being 32 bit. One example are the Links. The links between plugins uses a fixed with of 32bits per element. This is 'typeless' because in reality it could be any 32bit type so the buffer is defined as an array of char. Buffer size then is elements * element size. It then does a char array copy. The bigger the size of the element the longer it takes to copy. There are other places that also use byte arrays to hold data of any type.
Since the values are always 0, non-0 in SDR's we could be consistent and use Byte arrays everywhere (for SDR's) and save conversion and copy time. For links that are not SDR's we could still handle because the link is passing ArrayBuffer objects which know the type and length. But for SDR array's we could shorten the copy time by using Byte.
Anyway, that is my soapbox. Perhaps we should defer this for a separate PR and do some research into how best to handle SDR's as has been suggested in #109.
@@ -1248,8 +1245,8 @@ class SpatialPooler : public Serializable | |||
bool wrapAround_; | |||
UInt updatePeriod_; | |||
|
|||
Real synPermMin_; | |||
Real synPermMax_; | |||
Real synPermMin_ = 0.0f; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and same here,
does MSVC really complain about Real a = 0;
? It should be able to infer the exact type at compile-time. That's what all other compilers do.
And if it complains, I think we should do Real a = (Real)0;
instead (of = 0.0f
) because the (T)cast is more flexible if you decided to change using Real = double
you wouldn;t have to change all literals in codebase again.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
MSVC does handle 0 ok. But 5.0 is assumed to be a double and if being assigned to a float it is a type conversion.
My personal feeling is that all types should be specific and locked in. CSharp requires it. Python goes the other way and allows anything because values carry type at runtime. But Python pays for that flexibility in execution time.
for C, not C++. reduces compilation messages
set methods are mutex and disable the other automatically
@dkeeney ready for round 2 review, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks good.