AdamNiederer / faster

SIMD for humans
Mozilla Public License 2.0
1.56k stars 51 forks source link

Simple .zip() produces `assertion failed: !a.0.is_none() && a.0.unwrap().1 ... ` #12

Closed ralfbiedert closed 6 years ago

ralfbiedert commented 6 years ago

Hi,

When I try to run the following code:

#[cfg(test)]
mod tests {
    use faster::{IntoPackedRefIterator, IntoPackedZip, PackedZippedIterator, PackedIterator, Packed, f64s};

    #[test]
    fn test_faster_simd() {

        let a = vec![ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 ];
        let b = vec![ 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 ];

        let slice_a = &a[..];
        let slice_b = &b[..];

        let sum: f64 = (slice_a.simd_iter(), slice_b.simd_iter()).zip()
            .simd_map((f64s::splat(0f64), f64s::splat(0f64)), |(a,b)| (a - b) * (a - b))
            .simd_reduce(f64s::splat(0f64), f64s::splat(0f64), |a, v| a + v)
            .sum();

    }
}

I get:

---- kernel::rbf::tests::test_faster_simd stdout ----
    thread 'kernel::rbf::tests::test_faster_simd' panicked at 'assertion failed: !a.0.is_none() && a.0.unwrap().1 == a.0.unwrap().1 && !a.1.is_none() &&
    a.1.unwrap().1 == a.0.unwrap().1', /Users/rb/.cargo/registry/src/github.com-1ecc6299db9ec823/faster-0.4.0/src/zip.rs:306:0
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
stack backtrace:
   0: std::sys::unix::backtrace::tracing::imp::unwind_backtrace
   1: std::sys_common::backtrace::print
   2: std::panicking::default_hook::{{closure}}
   3: std::panicking::default_hook
   4: std::panicking::rust_panic_with_hook
   5: std::panicking::begin_panic
   6: ffsvm::kernel::rbf::tests::test_faster_simd
   7: <F as test::FnBox<T>>::call_box
   8: __rust_maybe_catch_panic

I'm using faster 0.4, and rust 1.25.0-nightly (4e3901d35 2018-01-23) and no target-feature. The same happens when I enable target-feature=+avx2. Unfortunately I don't really understand the assertion, so please let me know if there is something broken with the way I use faster.

AdamNiederer commented 6 years ago

I've noticed this as well. I'll have a fix ready in the next day or so.

AdamNiederer commented 6 years ago

Fixed in ec9af7c5c357296cd698a628bf490c1f9ddf1089 and 0.4.1

ralfbiedert commented 6 years ago

This still fails for

#[cfg(test)]
mod tests {
    use faster::{IntoPackedRefIterator, IntoPackedZip, PackedZippedIterator, PackedIterator, Packed, f64s};

    #[test]
    fn test_faster_simd() {

        let a = vec![ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 ];
        let b = vec![ 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 ];

        let slice_a = &a[..];
        let slice_b = &b[..];

        let sum: f64 = (slice_a.simd_iter(), slice_b.simd_iter()).zip()
            .simd_map((f64s::splat(0f64), f64s::splat(0f64)), |(a,b)| (a - b) * (a - b))
            // If you comment the next line out it works 
            .simd_reduce(f64s::splat(0f64), f64s::splat(0f64), |a, v| a + v )
            .sum();

    }
}
AdamNiederer commented 6 years ago

That's currently by design, because the API doesnt provide a good way to express what happens when one iterator returns a full vector while another iterator doesn't. I might revisit this when I do the iterator overhaul, but slicing down the larger vector or using a FnMut closure will probably be faster than what I can do.