Skip to content
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

Add basic SIMD support #523

Merged
merged 6 commits into from
Jun 29, 2018
Merged

Conversation

pitdicker
Copy link
Contributor

This is a rebased version of the branch from #377 (comment).

@TheIronBorn Do you want to review?

// those are usually more random.
let float_size = mem::size_of::<$f_scalar>() * 8;
let precision = $fraction_bits + 1;
let scale = $ty::splat(1.0 / ((1 as $u_scalar << precision) as $f_scalar));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: most arithmetic and bitwise operations allow you to just use scalar values:

let scale = $ty::splat(1.0 / ((1 as $u_scalar << precision) as $f_scalar));
scale * value
// is the same as
let scale = 1.0 / ((1 as $u_scalar << precision) as $f_scalar);
scale * value


let value: $uty = rng.gen();
let fraction = value >> (float_size - $fraction_bits);
fraction.into_float_with_exponent(0) - $ty::splat(1.0 - EPSILON / 2.0)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here. This would be the same:

fraction.into_float_with_exponent(0) - (1.0 - EPSILON / 2.0)

@TheIronBorn
Copy link
Collaborator

TheIronBorn commented Jun 21, 2018

Bug: https://github.com/pitdicker/rand/blob/209836f7c31aa04be3113c7fde5b82c9be8e6e84/src/distributions/uniform.rs#L600

assert!(low < high, "Uniform::new called with `low >= high`");

PartialOrdfor vectors compares two vectors lexicographically: https://github.com/gnzlbg/rfcs/blob/ppv/text/0000-ppv.md#traits-overview.

This will be fine on most inputs, but for inputs like new(f32x2::new(0.0, 100.0), f32x2::new(100.0, 0.0)) this assert will pass. We should probably have tests for these sort of cases.

The assertions need to be of the form low.lt(high).all()

@pitdicker
Copy link
Contributor Author

PartialOrdfor vectors compares two vectors lexicographically: https://github.com/gnzlbg/rfcs/blob/ppv/text/0000-ppv.md#traits-overview.

O wow, that is something easy to get wrong! Thank you for reviewing.

I have added a math_helpers module, with:

  • The WideningMultiply implementation from Uniform;
  • A trait for casting integers to floats. Normal floats need to use as, From is not implemented for the integer sizes we use. Vectors don't have as, and need From...
  • A trait to have natural comparison for both floats, and vectors. I only implemented the few things we need.

@pitdicker
Copy link
Contributor Author

The CI fails because of rust-lang/rust#51699.

Copy link
Member

@dhardy dhardy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, just some nits; meant to post this a couple of days ago

@@ -214,6 +214,7 @@ mod float;
mod integer;
#[cfg(feature="std")]
mod log_gamma;
mod math_helpers;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this any more mathematical than other parts of the library? You could just call it num_utils (i.e. Number Theory, though arguably that still covers most of the library) or arithmetic.


/// `PartialOrd` for vectors compares lexicographically. We want natural order.
/// Only the comparison functions we need are implemented.
pub trait NaturalCompare {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is natural depends on the context which is how PartialOrd confused you. How about SimultaneousOrd?

@dhardy
Copy link
Member

dhardy commented Jun 26, 2018

@TheIronBorn do you think this is ready?

I'd like to go over it in more detail myself still, but I think it's pretty neat that we can do this (it's well beyond what most random libs can offer)!

@TheIronBorn
Copy link
Collaborator

Looks good! I'll make an SIMD swap_bytes pull request once this merges

Copy link
Member

@dhardy dhardy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But other than those two things looks good.

BTW @TheIronBorn you can make a commit on top of @pitdicker's branch and push to your own branch if you have a fix, but best coordinate between yourselves.

unsafe {
let ptr = &mut vec;
let b_ptr = &mut *(ptr as *mut $ty as *mut [u8; $bits/8]);
rng.fill_bytes(b_ptr);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't look portable to me. Elsewhere we've made an effort to keep things portable; I don't think this needs to be an exception?

Unfortunately it doesn't look like the SIMD types support to_le. @TheIronBorn is this what you mean about using swap_bytes?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes that’s exactly where we’d use it

macro_rules! simd_impl {
($bits:expr,) => {};
($bits:expr, $ty:ty, $($ty_more:ty,)*) => {
simd_impl!($bits, $($ty_more,)*);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Neat usage of recursive macros.

But why do we need to pass $bits here instead of just using mem::size_of? It seems like an unnecessary risk of underfill/overfill.

@dhardy
Copy link
Member

dhardy commented Jun 29, 2018

Since @TheIronBorn has already addressed my comments, lets merge this and make a second PR for the fixes.

@dhardy dhardy merged commit 950c0af into rust-random:master Jun 29, 2018
@dhardy dhardy mentioned this pull request Jul 2, 2018
@dhardy dhardy mentioned this pull request Jul 13, 2018
28 tasks
@pitdicker pitdicker deleted the simd_support_basic branch July 20, 2018 16:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants