-
Notifications
You must be signed in to change notification settings - Fork 99
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
Better support for fold
#1823
Comments
Thank you for the test case. This is a great example of a performance problem that shouldn't exist, and we'll have to investigate. (There are several things in how we translate Rust code down to CBMC's IR that CBMC hasn't yet been "tuned" for. Vectors are a current focus area, but this seems like another one that likely has a very addressable cause...) (BTW: Since you use |
Thank you. I've also noticed issues with vectors. Is it worthwhile to submit an issue there as well?
Quite right! I made the correction. |
We are tracking some Vec issues here: #1676 Another thought I want to write down before I forget: I wonder if |
I added a for-iter version: pub fn array_sum_fold(x : [usize;100]) -> usize {
x.iter().fold(0, |accumulator, current| accumulator + current)
}
pub fn array_sum_for(x : [usize;100]) -> usize {
let mut accumulator : usize = 0;
for i in 0..100 {
accumulator += x[i];
}
accumulator
}
pub fn array_sum_for_iter(x : [usize;100]) -> usize {
let mut accumulator : usize = 0;
for i in x {
accumulator += i;
}
accumulator
}
#[cfg(kani)]
mod proofs {
use super::*;
#[kani::proof]
#[kani::unwind(101)]
fn array_sum_fold_proof() {
let x : [usize;100] = kani::any();
array_sum_fold(x);
}
#[kani::proof]
#[kani::unwind(101)]
fn array_sum_for_proof() {
let x : [usize;100] = kani::any();
array_sum_for(x);
}
#[kani::proof]
#[kani::unwind(101)]
fn array_sum_for_iter_proof() {
let x : [usize;100] = kani::any();
array_sum_for_iter(x);
}
} and I got the following numbers with 33e226b:
So the fold version seems to be at least 3X slower, and consumes ~6X more memory. |
It seems that the difference in performance is caused by iterators. Comparing these two versions, which are identical expect for the Without pub fn array_sum_for_iter1(x : [usize;100]) -> usize {
let mut accumulator: usize = 0;
for i in x {
accumulator += i;
}
accumulator
}
With pub fn array_sum_for_iter2(x : [usize;100]) -> usize {
let mut accumulator: usize = 0;
for i in x.iter() {
accumulator += i;
}
accumulator
}
|
I confess I thought those two would be the same. What does Oh wait, is it doing |
Yes, https://doc.rust-lang.org/std/iter/index.html#for-loops-and-intoiterator |
Well that brings to mind another option: |
Indeed, this version (slightly modified from yours due to a warning) performs the same as the IntoIterator::into_iter(x).fold(0, |accumulator, current| accumulator + current)
|
The changes hinted at in #1226 (comment) also bring down time for |
I tried this code:
using the following command line invocation:
with Kani version: 0.13.0
I expected to see this happen: Proof runtimes for the
fold
andfor
versions ofarray_sum
complete in roughly the same time.Instead, this happened:
kani
completed thefor
version quite quickly and then runs until eventually crashing (out of memory?) on thefold
version.The text was updated successfully, but these errors were encountered: