How the compiler decides which allocation is eliminated?

That makes sense too. I was using ntuple for a case where the N was determined at runtime.

h(x) = (ntuple(i -> 1, Val(x)); 0);

I was using ntuple inside a function of mine. And I was running into an issue where my function statically compiled for N = 10 but not for N = 11. Turns out trying to statically compile stuff is a great way to learn about what’s going on under the hood.

Edit: I wrote that poorly. Let me clarify. I was trying to statically compile my function once with N = 10 (known at compile time) and again with N = 11 (known at compile time). So basically two slightly different versions of the same function. I was able to statically compile in the first case but not the second. So I think your suggestion would work in my case.

ntuple(f, Val(N)) is great when N is a type parameter, but when it’s a literal, the most direct way to construct the tuple is to use the macro form: Base.@ntuple 11 i -> 1. This saves you from defining and passing an anonymous function/closure (in the context of the macro, the anonymous function is just convenient syntax, there’s no anonymous function after macro expansion).

Firstly, this digression on ntuple is completely off-topic, a mod would ideally move it to a new thread.

Which is it, then? Is it known at time of compilation or not? If it’s known at time of compilation there should be no allocation (depending on what exactly is meant by “known at compile time”).

:skull:

  • That’s not public.
  • There’s no benefit from using that here.

It is: Base.Cartesian · The Julia Language. It’s not exported, but that’s a different matter.

That’s usually true, but sometimes it’s just nicer to say directly what you’re trying to do instead of relying on inlining and compiler optimizations to eliminate the closure. I’ve had cases where ntuple(f, ::Val) failed to optimize as well as Base.@ntuple, but those were obviously a lot more complicated than this example.

I don’t want to digress from the topic here if this is deemed off topic. But I did read the title of the post before posting about tuples. It’s on topic in the sense that, if you tell the compiler ntuple won’t throw errors, it gets rid of the tuple creation and any intermediate allocations.

In my case, N was known at compile time (I was just doing something convoluted and didn’t realize it at first). But yeah trying to use tuples when you don’t know how many things you’re going to put in it might not be a type-stable way to go about things. That’s what arrays are for.

Happy for the topic to be split into another if people still want to continue this discussion on tuples. Or we can just stop here.

1 Like

@nsajko I handled the off-topic flag and marginally decided against splitting the topic. Yes, it’s a different case from an internals perspective, but goodness its surface is exactly the same, and the topic wasn’t so old. What is off-topic is admonishing others that you think it’s still off-topic — the way to raise that is with a flag and thank you for doing that first. Please directly message @moderators if you disagree with the way a particular flag was handled so as to not derail topics further.

Most importantly: there are some general commonalities here. Escape analysis is hard and the compiler is still fairly limited in this regard… and those limitations are fairly fundamental across function barriers and exceptions.

3 Likes

You link to the devdocs, which are specifically meant for documenting internals. Furthermore, a name being mentioned in the docs (even the usual documention, as opposed to the devdocs) doesn’t make the name public. Only names marked with public or export are public: Frequently Asked Questions · The Julia Language

This is the way to check:

julia> Symbol("@ntuple") ∈ names(Base)
false

… or …

julia> Base.ispublic(Base, Symbol("@ntuple"))
false

The help mode of the REPL also produces a warning meant for internals when querying Base.@ntuple.

You’re right! I didn’t notice as I got there through the search box.

You’re right again. That warning is new in 1.11. I missed it because 1.10 is still my daily driver (package compatibility reasons).

1 Like