Type instability with ntuple

While experimenting with some performance bottlenecks, I found that

h1(n) = ntuple(i -> collect(0:1/n:1), 3)
@code_warntype h1(5)

show type instability (it cannot infer 3 as the length of the tuple), while

f(n) = ntuple(i -> n, 3)
g(n) = collect(0:1/n:1)
h2(n) = f(g(n))
@code_warntype h2(5)

seems to be fine.
I feel like this is non-expected behaviour and if possible I’d like h1 to be type stable without the need to split it up like that. Is this a known issue or am I just doing things the wrong way?

On 0.6 both versions are type-unstable; presumably on 0.7 the second version is simple enough to benefit from the new constant-propagation optimization.

Anyway, you can pass Val{3}() if you want to force the length 3 to be a compile-time constant.

PS. Your h1 and h2 are inequivalent in another way: h1 has a different collected array in each tuple element, whereas h2 has a tuple of three references to the same array.

2 Likes

Sorry for not mentioning, I’m on 0.7 master right now.
Thanks! I didn’t even know you could pass Val{n}() to ntuple, that is nice.
There might be other calls to Base-functions in my code, where I can pass Val{n}()s to enforce type stability.

Yes, h1 and h2 are indeed different in that sense, I didn’t notice when I put together the example.

Note that you can write Val(3) instead. EDIT: On Julia 0.7

3 Likes