-
Notifications
You must be signed in to change notification settings - Fork 28
Non-deterministic test? #6
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
On Travis CI the
If I look into the covariance matrix obtained using the
This is due to the fn dot_generic<S2>(&self, rhs: &ArrayBase<S2, Ix1>) -> A
where S2: Data<Elem=A>,
A: LinalgScalar,
{
debug_assert_eq!(self.len(), rhs.len());
assert!(self.len() == rhs.len());
if let Some(self_s) = self.as_slice() {
if let Some(rhs_s) = rhs.as_slice() {
return numeric_util::unrolled_dot(self_s, rhs_s);
}
}
let mut sum = A::zero();
for i in 0..self.len() {
unsafe {
sum = sum.clone() + self.uget(i).clone() * rhs.uget(i).clone();
}
}
sum
} /// Compute the dot product.
///
/// `xs` and `ys` must be the same length
pub fn unrolled_dot<A>(xs: &[A], ys: &[A]) -> A
where A: LinalgScalar,
{
debug_assert_eq!(xs.len(), ys.len());
// eightfold unrolled so that floating point can be vectorized
// (even with strict floating point accuracy semantics)
let len = cmp::min(xs.len(), ys.len());
let mut xs = &xs[..len];
let mut ys = &ys[..len];
let mut sum = A::zero();
let (mut p0, mut p1, mut p2, mut p3,
mut p4, mut p5, mut p6, mut p7) =
(A::zero(), A::zero(), A::zero(), A::zero(),
A::zero(), A::zero(), A::zero(), A::zero());
while xs.len() >= 8 {
p0 = p0 + xs[0] * ys[0];
p1 = p1 + xs[1] * ys[1];
p2 = p2 + xs[2] * ys[2];
p3 = p3 + xs[3] * ys[3];
p4 = p4 + xs[4] * ys[4];
p5 = p5 + xs[5] * ys[5];
p6 = p6 + xs[6] * ys[6];
p7 = p7 + xs[7] * ys[7];
xs = &xs[8..];
ys = &ys[8..];
}
sum = sum + (p0 + p4);
sum = sum + (p1 + p5);
sum = sum + (p2 + p6);
sum = sum + (p3 + p7);
for i in 0..xs.len() {
if i >= 7 { break; }
unsafe {
// get_unchecked is needed to avoid the bounds check
sum = sum + xs[i] * *ys.get_unchecked(i);
}
}
sum
} Applying the same line of reasoning, |
I have added a test to check that the covariance matrix with zero observations is indeed a matrix filled with zeroes and once again I get different results on Travis CI vs local machine:
#[test]
fn test_covariance_zero_observations() {
let a = Array2::<f32>::zeros((2, 0));
// Negative ddof (-1 < 0) to avoid invalid-ddof panic
let cov = a.cov(-1.);
assert_eq!(cov.shape(), &[2, 2]);
assert!(cov.all_close(&Array2::<f32>::zeros((2, 2)), 1e-8));
} |
You've discovered a couple of bugs:
I don't have time right now to fix these things, but I'll take a look later. |
I think #7 should fix the nondeterministic behavior you are observing.
You can see the behavior of floating point division by zero with this program: fn main() {
for a in &[-1., -0., 0., 1.] {
for b in &[-0., 0.] {
println!("{:?} / {:?} = {:?}", a, b, a / b);
}
}
} The result is:
In other words, zero divided by zero is NaN, while non-zero divided by zero is ±inf (sign determined by both operands). For the >>> import numpy as np
>>> np.corrcoef(np.zeros((2, 0)))
/usr/lib/python3.7/site-packages/numpy/lib/function_base.py:356: RuntimeWarning: Mean of empty slice.
avg = a.mean(axis)
/usr/lib/python3.7/site-packages/numpy/core/_methods.py:78: RuntimeWarning: invalid value encountered in true_divide
ret, rcount, out=ret, casting='unsafe', subok=False)
/usr/lib/python3.7/site-packages/numpy/lib/function_base.py:2392: RuntimeWarning: Degrees of freedom <= 0 for slice
c = cov(x, y, rowvar)
/usr/lib/python3.7/site-packages/numpy/lib/function_base.py:2326: RuntimeWarning: divide by zero encountered in true_divide
c *= np.true_divide(1, fact)
/usr/lib/python3.7/site-packages/numpy/lib/function_base.py:2326: RuntimeWarning: invalid value encountered in multiply
c *= np.true_divide(1, fact)
array([[nan, nan],
[nan, nan]]) |
Great - thanks for the quick fix! |
This test fails on Travis, for #5, while it succeeds on my local machine.
It's weird - any idea? @jturner314
I am trying to reproduce the error, but I am failing.
The text was updated successfully, but these errors were encountered: