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

SpatialPooler cleanup #108

Merged
merged 29 commits into from
Nov 15, 2018
Merged

SpatialPooler cleanup #108

merged 29 commits into from
Nov 15, 2018

Conversation

breznak
Copy link
Member

@breznak breznak commented Nov 14, 2018

  • cleanup SP code
  • add lots of const qualifiers
  • add asserts and checks to get/setters
  • some optimizations

@breznak breznak added optimization code code enhancement, optimization, cleanup..programmer stuff labels Nov 14, 2018
@breznak breznak added this to the optimization milestone Nov 14, 2018
@breznak breznak self-assigned this Nov 14, 2018
@breznak breznak requested a review from dkeeney November 14, 2018 03:56
@breznak breznak closed this Nov 14, 2018
@breznak
Copy link
Member Author

breznak commented Nov 14, 2018

Restarting stuck CI

@breznak breznak reopened this Nov 14, 2018
- fix deactivation value to 0
- document mutual exclusion (mutex) with numActivePerInhArea
- MAX_LOCALAREADENSITY explains 0.5 value
@breznak breznak added the ready label Nov 14, 2018
@breznak
Copy link
Member Author

breznak commented Nov 14, 2018

@dkeeney please review, SP cleanup& optimization

why is it not initialized in initialize()
Copy link
Member Author

@breznak breznak left a 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;
Copy link
Member Author

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

src/nupic/algorithms/SpatialPooler.hpp Outdated Show resolved Hide resolved

void boostOverlaps_(vector<UInt> &overlaps, vector<Real> &boostedOverlaps);
void boostOverlaps_(const vector<UInt> &overlaps, vector<Real> &boostedOverlaps) const;
Copy link
Member Author

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?!
Copy link
Member Author

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();
Copy link
Member Author

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;
Copy link
Member Author

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_);
Copy link

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.

Copy link
Member Author

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?

dkeeney
dkeeney previously approved these changes Nov 14, 2018
Copy link

@dkeeney dkeeney left a 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.

@dkeeney
Copy link

dkeeney commented Nov 14, 2018

Is there a way to just turn off appveyor for now?

@breznak
Copy link
Member Author

breznak commented Nov 14, 2018

Suggest changing all Real's to Real32 so we lock in the size. Same with Int and UInt.

is this an advantage? Would sb want to run on Real(64)?
Anyway,
using Real = Real32; should do, right?

n many cases these are actually SDR arrays so they should be perhaps Byte arrays but maybe that would be going too far for now.

Too far. My plan is to separate into smaller pieces in #92 and then focus on the common SDR-type #109

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

Will do!

because I cannot see what the type is but that is just me.

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.

Copy link
Member Author

@breznak breznak left a 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;
Copy link
Member Author

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.

Copy link

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;
Copy link
Member Author

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.

Copy link

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.

@breznak breznak closed this Nov 15, 2018
@breznak breznak reopened this Nov 15, 2018
@breznak breznak closed this Nov 15, 2018
@breznak breznak reopened this Nov 15, 2018
@breznak breznak closed this Nov 15, 2018
@breznak breznak reopened this Nov 15, 2018
set methods are mutex and disable the other automatically
@breznak
Copy link
Member Author

breznak commented Nov 15, 2018

@dkeeney ready for round 2 review,
I've managed to turn off the Windows CI (unused)
and fixed API compliance (disabled=-1, thanks for spotting that!)

Copy link

@dkeeney dkeeney left a comment

Choose a reason for hiding this comment

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

looks good.

@dkeeney dkeeney merged commit 6c41a83 into master Nov 15, 2018
@breznak breznak deleted the sp_cleanup branch November 15, 2018 15:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
code code enhancement, optimization, cleanup..programmer stuff optimization ready
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants