erlang / otp

Erlang/OTP
http://erlang.org
Apache License 2.0
11.37k stars 2.95k forks source link

Allow aligned allocations in NIFs #6665

Open hauleth opened 1 year ago

hauleth commented 1 year ago

Is your feature request related to a problem? Please describe.

When using Rust (via Rustler) it would be handy to have a way to use Rust GlobalAlloc with enif_alloc function. The problem is that enif_alloc do not have counterpart that allows passing alignment, which would be needed there. This can sometimes lead to SIGBUS errors.

Describe the solution you'd like

Have another allocation function (for example void *enif_alloc_aligned(size_t size, size_t alignment)) that would allow to explicitly set the alignment. It will then pick the max(erlang_alignment, alignment) and will use that as the target alignment (AFAIK we can always expand alignment, but never contract it).

With such hypothetical function we could then implement Rust GlobalAlloc as:

struct ErlGlobalAlloc;

unsafe impl GlobalAlloc for ErlGlobalAlloc {
    fn alloc(&self, layout: Layout) -> *mut u8 {
        enif_alloc_aligned(layout.size, layout.align)
    }

    // Rest of the functions
}

Describe alternatives you've considered

I was thinking about implementing this as try and error or by doing some extra magic with allocating more memory than needed and then storing required metadata there, but all of that is just set of hacks, that could be instead implemented directly in OTP.

Additional context

I believe that it would be useful to have such function, as it may help with having Rust global allocator that will allow introspection and observability of memory usage in Rustler NIFs.

hauleth commented 1 year ago

I see that there already is such function in ERTS, but I am not experienced enough right now to come up with an idea how to expose such function there.

sverker commented 1 year ago

I see that there already is such function in ERTS

What function are you referring to?

hauleth commented 1 year ago

erts_sys_aligned_alloc in erts/emulator/sys/unix/sys.c and erts/emulator/sys/win32/sys.c

PastMoments commented 1 year ago

I'm also in need of this (or something similar). For me, I am attempting to use enif_alloc_resource with SIMD intrinsics. From what I'm seeing, __m256d (4 packed doubles) requires a 32 byte alignment, but the address given by enif_alloc_resource is often not properly aligned, causing a crash.

filmor commented 2 months ago

@hauleth I added GlobalAlloc support for Rustler a while ago in https://github.com/rusterlium/rustler/pull/580. A custom alignment for enif_alloc would still be highly appreciated, less code is always better :)

I'll try to create a PR for this.

ityonemo commented 3 weeks ago

currently tracking it in zigler:

https://github.com/E-xyza/zigler/issues/488

though here we use a custom allocator for wide alignments:

https://github.com/E-xyza/zigler/blob/93f9526e477867770e5f075343b1f396e000d704/priv/beam/allocator.zig#L86-L132

If there's a better internally supported choice, that would be amazing.