-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Remove a source of O(n^2) running time in bigints. #12209
Conversation
Cool; there's another instance of almost exactly the same pattern on line ~440, could you do this change there as well? |
r=me if you do that and add a let n = BigUint::from_uint(1) << 1000;
bh.iter(|| {
let mut m = n.clone();
for _ in range(0, 100) {
m = m >> 1;
}
}) (Adjust the 100 & 1000 constants as necessary to get a reasonable benchmark.) |
@huonw I'm not sure the two cases are analogous. In the case that my commit is addressing, the generated vector is of O(n) length, where n is the length of the input. Thus building via repeated unshifting is taking O(n^2) time. In the case on line ~440 (within Given that, I think we should just leave the loop on line ~440 alone. If my hypothesis above is correct, then it should be replaced with code to just handle the two cases of I will however add the |
Good catch! It certainly looks like it. |
On Wed, Feb 12, 2014 at 02:30:49AM -0800, Felix S Klock II wrote:
We have to be very careful about the cleanups here in case of |
On Wed, Feb 12, 2014 at 02:30:49AM -0800, Felix S Klock II wrote:
Oh, I guess you can leave memory at the front uninitialized, and then |
::num::bigint, Remove a source of O(n^2) running time in `fn shr_bits`. I'll cut to the chase: On my laptop, this brings the running time on `pidigits 2000` (from src/test/bench/shootout-pidigits.rs) from this: ``` % time ./pidigits 2000 > /dev/null real 0m7.695s user 0m7.690s sys 0m0.005s ``` to this: ``` % time ./pidigits 2000 > /dev/null real 0m0.322s user 0m0.318s sys 0m0.004s ``` The previous code was building up a vector by repeatedly making a fresh copy for each element that was unshifted onto the front, yielding quadratic running time. This fixes that by building up the vector in reverse order (pushing elements onto the end) and then reversing it. (Another option would be to build up a zero-initialized vector of the desired length and then installing all of the shifted result elements into their target index, but this was easier to hack up quickly, and yields the desired asymptotic improvement. I have been thinking of adding a `vec::from_fn_rev` to handle this case, maybe I will try that this weekend.)
Nice find, @pnkfelix |
fix: Fix config patching failing when appending suffixes
::num::bigint, Remove a source of O(n^2) running time in
fn shr_bits
.I'll cut to the chase: On my laptop, this brings the running time on
pidigits 2000
(from src/test/bench/shootout-pidigits.rs) from this:to this:
The previous code was building up a vector by repeatedly making a
fresh copy for each element that was unshifted onto the front,
yielding quadratic running time. This fixes that by building up the
vector in reverse order (pushing elements onto the end) and then
reversing it.
(Another option would be to build up a zero-initialized vector of the
desired length and then installing all of the shifted result elements
into their target index, but this was easier to hack up quickly, and
yields the desired asymptotic improvement. I have been thinking of
adding a
vec::from_fn_rev
to handle this case, maybe I will try thatthis weekend.)