Skip to content

Commit 1d79230

Browse files
committed
add aligned slice allocation utilities
1 parent a1ea2a3 commit 1d79230

File tree

1 file changed

+71
-0
lines changed

1 file changed

+71
-0
lines changed

source/mir/ndslice/allocation.d

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,36 @@ version(mir_test)
202202
static assert(is(typeof(tensor) == Slice!(Contiguous, [3], int*)));
203203
}
204204

205+
/++
206+
Allocates an uninitialized aligned array and creates an n-dimensional slice over it.
207+
Params:
208+
lengths = list of lengths for each dimension
209+
alignment = memory alignment (bytes)
210+
Returns:
211+
contiguous uninitialized n-dimensional slice
212+
+/
213+
auto uninitAlignedSlice(T, size_t N)(size_t[N] lengths, uint alignment) @system
214+
{
215+
immutable len = lengths.lengthsProduct;
216+
import std.array : uninitializedArray;
217+
auto barr = uninitializedArray!(byte[])(len * T.sizeof + alignment);
218+
size_t offset = alignment + size_t.sizeof * 2 - 1;
219+
void* basePtr = uninitializedArray!(byte[])(len * T.sizeof + offset).ptr;
220+
void* alignedPtr = cast(void**)((cast(size_t)(basePtr) + offset) & ~(alignment - 1));
221+
return (cast(T*) alignedPtr).sliced(lengths);
222+
}
223+
224+
///
225+
version(mir_test)
226+
@system pure nothrow unittest
227+
{
228+
auto tensor = uninitAlignedSlice!double([5, 6, 7], 64);
229+
assert(tensor.length == 5);
230+
assert(tensor.elementsCount == 5 * 6 * 7);
231+
assert(cast(size_t)(tensor.ptr) % 64 == 0);
232+
static assert(is(typeof(tensor) == Slice!(Contiguous, [3], double*)));
233+
}
234+
205235
/++
206236
Allocates an array through a specified allocator and creates an n-dimensional slice over it.
207237
See also $(MREF std, experimental, allocator).
@@ -572,3 +602,44 @@ unittest
572602
s.stdcFreeSlice;
573603
t.stdcFreeSlice;
574604
}
605+
606+
/++
607+
Allocates an uninitialized aligned array using `core.stdc.stdlib.malloc` and creates an n-dimensional slice over it.
608+
Params:
609+
lengths = list of lengths for each dimension
610+
alignment = memory alignment (bytes)
611+
Returns:
612+
contiguous uninitialized n-dimensional slice
613+
+/
614+
auto stdcUninitAlignedSlice(T, size_t N)(size_t[N] lengths, uint alignment) @system
615+
{
616+
immutable len = lengths.lengthsProduct;
617+
import mir.internal.memory: alignedAllocate;
618+
auto arr = (cast(T*)alignedAllocate(len * T.sizeof, alignment))[0 .. len];
619+
return arr.sliced(lengths);
620+
}
621+
622+
///
623+
version(mir_test)
624+
@system pure nothrow unittest
625+
{
626+
auto tensor = stdcUninitAlignedSlice!double([5, 6, 7], 64);
627+
assert(tensor.length == 5);
628+
assert(tensor.elementsCount == 5 * 6 * 7);
629+
assert(cast(size_t)(tensor.ptr) % 64 == 0);
630+
static assert(is(typeof(tensor) == Slice!(Contiguous, [3], double*)));
631+
stdcFreeAlignedSlice(tensor);
632+
}
633+
634+
/++
635+
Frees aligned memory allocaged by CRuntime.
636+
Params:
637+
slice = n-dimensional slice
638+
See_also:
639+
$(LREF stdcSlice), $(LREF stdcUninitSlice)
640+
+/
641+
void stdcFreeAlignedSlice(size_t[] packs, T)(Slice!(Contiguous, packs, T*) slice)
642+
{
643+
import mir.internal.memory: alignedFree;
644+
slice._iterator.alignedFree;
645+
}

0 commit comments

Comments
 (0)