Retrieve strides from `jl_array_t`


#1

Is there a means to retrieve the strides of a julia array from the C API?

https://docs.julialang.org/en/stable/stdlib/arrays/#Base.strides

The only property accessors available in julia.h apparently are

JL_DLLEXPORT void *jl_array_ptr(jl_array_t *a);
JL_DLLEXPORT void *jl_array_eltype(jl_value_t *a);
JL_DLLEXPORT int jl_array_rank(jl_value_t *a);
JL_DLLEXPORT size_t jl_array_size(jl_value_t *a, int d);

If I can avoid recomputing the strides on the C++ side, that would be fantastic.


#2

jl_array_t are Array and are always column major dense array.


#3

I know, in xtensor-julia, we do compute the column-major strides.

See e.g. https://github.com/QuantStack/xtensor-julia/blob/master/deps/xtensor-julia/include/xtensor-julia/jltensor.hpp#L134

but I guess that you already compute strides and store them in the memory representation of Julia arrays for efficiency.

It would be more efficient to me to be able to access them, just like we do in xtensor-python, but wrapping the strides from the buffer protocol.

See e.g. https://github.com/QuantStack/xtensor-python/blob/master/include/xtensor-python/pyarray.hpp#L494

Is there a means to access the strides computed by Julia from the C API?


#4

No, the strides aren’t pre-computed and cached. Only the dimension sizes themselves are stored. Here’s the array header definition: https://github.com/JuliaLang/julia/blob/4a814806811d13b350a3f6c04cb839ad4c9236f1/src/julia.h#L143-L162

And here’s the implementation of converting an n-dimensional index to an offset: https://github.com/JuliaLang/julia/blob/1093977c989a3f7bef4e791d58055c30ee2fee10/src/builtins.c#L906-L927


#5

Well, the dimensions are essentially the strides, in units of sizeof the elements. Typically, in C, you would access a Julia column-major array A[i1,i2,i3] via

Adata[i1-1 + n1*(i2-1 + n2*(i3-1))]

where Adata is a pointer (of the appropriate type) to the underlying data and n1 and n2 are the sizes of the first two dimensions, and I’ve subtracted 1 to convert between 1-based and 0-based indexing. By parenthesizing it like this, no additional stride calculations are needed.


#6

It’s not really related to the strides, but note that ArrayRef in CxxWrap.jl makes working with native Julia arrays from C++ slightly easier:

The current API is limited to what I needed, so it doesn’t implement multi-dimensional indexing and you will still need to use @stevengj 's formula.


#7

Thanks guys, this clarifies things quite a bit.