Is there a way to tell a Vec<u8> to align on 64 byte boundaries?

let x: Vec<u8>

is there a way to tell the compiler to align the elements of the Vec so that x[0..63], x[64..127], x[128..191], ... are on 64 byte cache lines ?

There's no direct way to do this.

You could tell Rust to use a custom allocator, and make your allocator return only 64-byte aligned allocations. But other than such massive hack, there's no safe and reliable method. Even if you manage to create such Vec, it can lose this property after reallocation.

You need to use Vec<T> where T naturally has the required alignment. Note that it will work only for T, and it's always unsafe to transmute that to Vec<u8> due to Vec deallocating its content using its type's Layout, and the Layout must have matching alignment.

It's fine to do that with borrowed slices, since they don't deallocate.

1 Like

See also align_to{,_mut}.

2 Likes

Do you really need a Vec aligned like that, @zeroexcuses ?

This is completely feasible if you just needs a slice aligned that much instead.

1 Like

How would this happen, given a custom allocator?

I believe they're referring to any solution "other than such massive hack" in that sentence.

It would be possible to create a Vec<AlignedTo64> and then unsafely convert it to a (mutable) slice on the fly when needed:

#[derive(Clone, Debug)]
#[repr(C, align(64))]
struct AlignedSubslice {
    array: [u8; 64]
}

let buf: Vec<AlignedSubslice> = vec![AlignedSubslice { array: [42; 64] }; 4];

let view: &[u8] = unsafe {
    assert_eq!(size_of::<AlignedSubslice>(), size_of::<[u8; 64]>());
    assert_eq!(align_of::<AlignedSubslice>(), 64);
    
    slice::from_raw_parts(
        buf.as_ptr().cast::<u8>(),
        buf.len() * size_of::<AlignedSubslice>(),
    )
};

I wouldn't recommend this, nevertheless. Having to mess with alignments by hand outside of FFI is usually an indication of a missing abstraction. What are you trying to do?

2 Likes

XY problem: micro optimizations seeing if I can make sub slices cache aligned to 64 bytes

You can try the above unsafe realigning code, then.

But since you are only using this for optimization, you may also want to look at <[T]>::align_to<U>() which is defined in std. It does the pointer casting part for you, but you still have to consider soundness.