-
Notifications
You must be signed in to change notification settings - Fork 32
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
Fix operations with self #35
Conversation
src/bigints.nim
Outdated
s = newSeq[T](newlen) | ||
else: | ||
s.setLen(newlen) | ||
let t = s |
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.
I guess this change sacrifices performance. I'm not really against it though, just wanted to clarify.
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.
Yes, I guess you are right. I think it makes sense to do a small benchmarking. Also I could make available old behaviour behind a switch (e.g. bigintsUseOldSetXLen). And if the benchmarking show too much of a degradation I could try to think of a new way to make the fix.
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.
But the old behaviour is so easy to get wrong that the better performance is probably not important.
bigints.nimble
Outdated
@@ -1,6 +1,6 @@ | |||
# Package | |||
|
|||
version = "0.4.4" | |||
version = "0.4.5" |
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.
Should I release after this is merged? Maybe a larger number like 0.5 is appropriate?
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.
Yes, if there is performance degradation it would probably call for an increase of minor version. In that case probably the best would be to tag current master as 0.4.4 (otherwise I am not sure nimble is able to pick up the correct version if asked to require bigints <= 0.4.4). And then after the changes we could tag also the new release. Anyway let's see after I do some benchmarking
After review, open points:
regarding other options I was thinking of having a check inside functions where SetXLen might cause issue. The check should check if we are using the same input and probably the best way would be to check if limbs have same addr. Need to think this through anyway. |
finally added the benchmarking against old setXLen. I am a bit disappointed that chainedAddition task almost doubles its time, so I am now thinking that I should consider other options for the fix as outlined in last comment. For other comments regarding benchmark results: simple addition and multiplication are not impacted, which is kind of expected. I was surprised that chainedMultiplication is not impacted as much as chainedAddition: I guess this is because multiplication even with old setXLen needs to copy the sequence since the memory allocated is not sufficient to extend. In principle the optimal way to deal with var that grow is to preallocate a seq with enough capacity (if possible). I guess this is doable with current API (there is an init that can get as parameter the seq of limbs and this can be created with a preset capacity). Below the automatic benchmarking report (available also here). A few notes on benchmark implementation:
Benchmark resultsaddition100d
chainedAddition100d,3i
100d,33i
multiplication100d
chainedMultiplication10d,3i
|
Sorry for leaving this open for such a long time... I think the easiest option would be actually merging the fix (bumping the version) and maybe opening an issue to track the possibility of further improvement. In the next days I plan to clean up this towards this goal. |
cleaned up (removed also the benchmarks, if this branch is not deleted the code should be still available in this commit) and ready to be merged. also created the issue for tracking performance regression: https://github.com/def-/nim-bigints/issues/36 After merging remember to tag the release both of 0.5.0 (latest commit after merge) and of 0.4.4 (latest commit before merge), so that nimble can pick up requirements <= 0.4.4 in case someone wants to use it. |
Thanks, will tag them. |
This was a bit tricky. Fixes #27 and problem with self multiplication.
Essentially the issue was that for a generic operation
op(a: var BigInt, b: BigInt, c: BigInt)
when callingsetXLen
ona.limbs
ifb
is the same asa
thenb.limbs
gets reset to empty insideop
(andc
is only involved for computing resetting length). For a minimal example that shows this (playground):output:
Note that the "reset" is not always the case, in particular issue #27 if added to the tester.nim file did not raise an error, while it raises an error when in a separate file (
tissue27.nim
, added to tests). This is possibly due to the fact that when resetting length, in the heap there is space for lengthening the sequence without copying (probably the sequence was allocated in a space previously occupied by a longer sequence).The fix I propose is to change behaviour of SetXLen to always create a new sequence and copying the content according to new length.
unrelated change: added
.exe
to.gitignore
.