I need to reproduce a code in a Kernel include file. In a part, it computes the size of an array of chars. Initially, I was doing something like this, which perfectly mimics the behavior in the .h:
function test(a::AbstractVector)
m = length(a)
return sizeof(NTuple{m, Cchar})
end
The allocation is coming from the type NTuple{m, Cchar} that depends on m. Of course I can avoid it by just replacing with m*sizeof(Cchar). However, this leads to many changes in a lot of functions. Thus, is there a way to create a type so that sizeof returns what I want without allocations?
Not sure I understand, but would this work for you?
struct Foo{T}
nelems :: Int
end
Foo(nelems, T) = Foo{T}(nelems)
Base.sizeof(x :: Foo{T}) where {T} = x.nelems * sizeof(T)
function test(a::AbstractVector)
m = length(a)
return sizeof(Foo(m, Cchar))
end
julia> using BenchmarkTools
julia> data = [1,2,3,4];
julia> @btime test($data)
1.879 ns (0 allocations: 0 bytes)
4
I mean, just do the changes then? This feels a bit like saying that the car runs slowly because there’s a puncture on all tires and asking if there is any way to make it faster that doesn’t involve changing the tires.
Creating a type using runtime information is kind of the definition of “not type-stable”.
However, if the C code that you are translating is passing a fixed-length data vector then you could translate that into a Tuple or an SVector or MVector (from StaticArrays) instead of a Vector. That will make m a compile-time constant, and get rid of the allocations.
I mean, if I change this, then I will loose the 1 to 1 relationship with the kernel functions. Thus, maybe in the future, if the kernel API changes, then it will be a little harder to update this file. Of course this is not the end of the world, I am just curious how can I avoid that problem
Nice, the idea to overload sizeof just for that case was very good! Thanks!
Hum, I see. Unfortunately I can’t. Because this vector contains the message the user wants to transmit using SPI interface. It will be very bad to restrict to only the type in StaticArrays.jl. What I can do, it to force the user to use Tuples instead. I will see, but the proposal of @ffevotte seems very good.
Note that it’s not the overloading of sizeof that matters. It’s the fact that Foo doesn’t get m as a type parameter. Essentially, this is just a very convoluted way of writing m*sizeof(Cchar).