-
Notifications
You must be signed in to change notification settings - Fork 59
locate() does not implement borrow check? #138
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
Comments
@polarathene I think I found the problem. The bug was in indexing code and not in af::locate. Using the below code extern crate arrayfire as af;
use af::*;
fn main() {
let dims = af::Dim4::new(&[1, 3, 1, 1]);
let bools = af::Array::new(&[1, 0, 1], dims);
let values = af::Array::new(&[2, 5, 6], dims);
print( &bools );
print( &filter_edited(&values, &bools) );
print( &af::locate(&bools) );
print( &filter_edited(&values, &af::locate(&bools)) );
print( &filter_original(&values, &bools) );
}
fn filter_edited(array: &af::Array, bools: &af::Array) -> af::Array {
let mut idxr = af::Indexer::new();
idxr.set_index(bools, 0, None);
af::index_gen(array, idxr)
}
fn filter_original(array: &af::Array, bools: &af::Array) -> af::Array {
let mut idxr = af::Indexer::new();
idxr.set_index(&af::locate(bools), 0, None);
af::index_gen(array, idxr)
} I don't get the below corrupted output for filter_original after the fix.
After the fix, the following code gives expected output. fn filter_original(array: &af::Array, bools: &af::Array) -> af::Array {
let mut idxr = af::Indexer::new();
idxr.set_index(&af::locate(bools), 1, None);
// Note that indexing dimension is not 0, and input is 2d [1 3 1 1], unlike [3 1 1 1] which is treated as one dimensional by ArrayFire.
af::index_gen(array, idxr)
}
fn filter_original(array: &af::Array, bools: &af::Array) -> af::Array {
let mut idxr = af::Indexer::new();
idxr.set_index(&af::locate(bools), 0, None);
af::index_gen(array, idxr)
}
|
That's interesting, my current version is: fn filter_array(array: &af::Array, bools: &af::Array) -> af::Array {
let mut idxr = af::Indexer::new();
let indices = &af::locate(bools); // Assigning a variable first was required
idxr.set_index(indices, 0, None);
&af::index_gen(array, idxr)
} Which is similar to what my edited version I shared earlier did, not sure why the behaviour was different. Was it due to set_index with 0 instead of 1 for dimension on a [1,3,1,1] array? Oh I see the output shifted the dimension, I thought this was expected due to a new array. |
What do you mean by shifted the dimension ? May be I confused you, I shall try to explain in detail once again. The dimension with which set_index is called will have an effect on how the output looks like. In this case, input array is considered 2D because there are > 1 elements along second dimension. The indexing operations will repeat elements if index array size is greater than the number of elements of array along given dimension. Lets take the example we have used to debug this issue. set_index is called with 0 as dim and input is of dims [1 3 1 1]. Since the input array has only one element along first(0th) dimension, for every index along that dimension, the only existing element is repeated because all indices point to the same element. Thus we see the following output
Also, |
Yes, I think we're on the same page there. Prior [1,3,1,1] as reported when set_index was applied, the array returned was [3,1,1,1]. This isn't what was meant to happen according to info here, and instead the result you shared should have happened unless the correct dimension was given to set_index to return [1,2,1,1] (not [2,1,1,1]) with elements [2,6] instead. |
I ran into the issue I described with locate on another function. Where my solution above does: let indices = &af::locate(bools); // Assigning a variable first was required
idxr.set_index(indices, 0, None); Instead of the original that did: idxr.set_index(&af::locate(bools), 0, None); Which caused problems described in the other thread. You can see that instead of assigning to a variable -- I just tried out the let c = &randu::<f32>(Dim4::new(&[5, 3, 1, 1]));
let d = join_many![2; a, b, c]; As in the example works but apparently this is not the same? let c = randu::<f32>(Dim4::new(&[5, 3, 1, 1]));
let d = join_many![2; a, b, &c];
I know that you have apparently fixed this due to indexing, but is that fix addressing what this issue was referring to specifically?
Rather than the dims, this subtle change might behave diferently and the borrow checker might be able to pick up on it was a suggestion a user made when I first ran into the issue with When I check type with |
Avoiding the |
@polarathene I shall look into the macro. Thank you once again for reporting it. |
@polarathene The error |
@9prady9 Good to know, another bug fixed :) |
I am not sure if |
I am used to creating my arrays as shown elsewhere not with the variable assignment of the call being referenced. When I use AF methods I add the reference. The If you'd like an experienced opinion the guys on #rust-beginners IRC channel are very helpful and knowledgeable. Some are Rustlang devs and could advise what might be best :) The examples also tend to avoid assigning Arrays like the join_many! macro example does. If it is preferrable to create Arrays like shown in |
I have created an issue for improvement of macros, #144, you can track the progress of it over there. |
Closing this issue as locate doesn't have issues as suspected earlier. Please follow the indexing issue progress on the #149. |
@polarathene I have put in a fix for this in devel just now. Can you please test it on your end and let me know if everything is working fine. The borrow check will complain now if you are using temporarily allocated Arrays to call set_index. |
@9prady9 Compiling with latest devel with this function in my src:
Error:
So my "fix" earlier was incorrect? :P Or was this unintended? |
Compiler is happy with this change:
|
It's also happy if I change the set_index line to |
@polarathene That's odd Edited: |
fyi - 8893683 should be the hash of latest devel HEAD. |
I can confirm I'm on that commit. |
This is what I get on my machine if we do
True, that was the initial way in which the code stub in stream compaction was implemented. But, that is a buggy code even though it worked in few cases earlier. |
Oh the latest commit should be throwing an error for that? Maybe I need to do a cargo clean, hold on. |
Cargo clean seemed to fix that. fn filter_edited(array: &af::Array, bools: &af::Array) -> af::Array {
let mut idxr = af::Indexer::new();
idxr.set_index(bools, 0, None);
af::index_gen(array, idxr)
}
fn filter_original(array: &af::Array, bools: &af::Array) -> af::Array {
let mut idxr = af::Indexer::new();
let indices = &af::locate(bools);
idxr.set_index(indices, 0, None);
af::index_gen(array, idxr)
} Errors:
|
1st errror was referring to this: fn filter_with_index(array: &af::Array, bools: &af::Array) -> af::Array {
let mut idxr = af::Indexer::new();
let indices = af::locate(bools);
idxr.set_index(&indices, 0, None);
join(0, &af::index_gen(array, idxr), &indices)
} 2nd to filter_original() |
You have to move |
@polarathene Is it clear now why |
@9prady9 Thanks that fixed it, I was just about to ask how I was meant to use the method now :P First time I've seen the order of declaration matter like that. I'm still reasonably fresh to Rust, so I don't quite grasp the ownership/borrowing/lifetimes fully yet. I can see that tripping up other users who might not be experienced enough with Rust, though an example snippet with the correct order would probably get copy/pasted or could be noticed on a tutorial/example about indexing with the Rust wrapper :) The note is good, I didn't actually read it until just now ha. And yes I get why now sort of, in the sense that Definitely a helpful note to include in docs/faq somewhere :) |
@polarathene The business of borrow checking references is surely confusing for a while in the beginning. I took me a while to understand that lifetime of references in set_index call are the reason why borrow checker did not complain earlier. However, the rust compiler's error messages is what guided me in fixing this problem. I guess this order of creation plays a significant role when objects and references come into play. For integral types where copy trait is implicitly defined, this won't be an issue at all. While I was at fixing this bug, I used the code you shared with me to debug the problem to write a basic example in the documentation for |
See my comments on this issue. I've provided a test sample to demonstrate slight change in when locate is used that provides an incorrect result or triggers a not so helpful panic depending on dims used. I've been told that making use of the borrow checker can inform users at compile time when the API is used incorrectly.
Based on other errors/discrepencies with other AF functions causing confusion for me, I think many other functions would benefit from this?
The text was updated successfully, but these errors were encountered: