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

Support MaybeUninit #152

Open
QuarticCat opened this issue Feb 27, 2023 · 3 comments
Open

Support MaybeUninit #152

QuarticCat opened this issue Feb 27, 2023 · 3 comments

Comments

@QuarticCat
Copy link

Currently, all_reduce_into and some other APIs only accept buffers like &mut [f32] but not &mut [MaybeUninit<f32>]. However, It's common to use &mut [MaybeUninit<f32>] as a receive buffer. We need lib support for this, as casting a uninitialized buffer to &mut [T] might be undefined behavior, see [1], [2], and [3].

Note that we cannot simply implement Equivalence for MaybeUninit<T> where T: Equivalence<Out = SystemDatatype>, which gives users the right to pass an uninitialized buffer as a send buffer, so that APIs like all_reduce_into are not safe anymore.

@jedbrown
Copy link
Contributor

I agree this would be useful in some form, though there are issues. There is related discussion in #133 that we should consider.

@jedbrown
Copy link
Contributor

So the straightforward user interface might look like

// this is safe because `assume_init` applies to the `MaybeUninit<f64>`, but you get the buffer somehow
let mut buffer: [MaybeUninit<f64>; 4] = unsafe { MaybeUninit::uninit().assume_init() };

let recv: &mut [MaybeUninit<f64>] = &mut buffer[..]; // slice to receive into
comm.all_reduce_into(send, recv, op);
let recv: &mut [f64] = unsafe { MaybeUninit::slice_assume_init_mut(recv) }; // nightly API or can be done with transmute

I think that's pretty undesirable because that unsafe line at the bottom is easy for callers to mess up (and a bit worse without using the nightly-only experimental API).

What about this?

let recv: &mut [MaybeUninit<f64>] = &mut buffer[..]; // slice to receive into
let recv: &mut [f64] = comm.all_reduce_into_uninit(send, recv, op);

Note that I used overly type annotations above, and in practice, you'd just write:

let recv = comm.all_reduce_into_uninit(send, &mut buffer[..], op);

@QuarticCat
Copy link
Author

I've left the original project that needed this feature for a long time and forgot some details. But the all_reduce_into_uninit API looks good to me.

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

No branches or pull requests

2 participants