(Advanced) User means of reasoning about copy elision?

HI Chapel Devs —

While working with @twesterhout today, he was asking about copy elision in Chapel and particularly:

  • whether there is a means for a(n advanced) user to get feedback from the compiler about when copy elision is or is not happening
  • what options there are for a user to exert more control over copy elision if they want to assert that it should be done in a given case.

For the first question, I wasn't sure and wasn't seeing any developer compiler flags that jumped out at me as providing such a report, so wanted to see what @mppf would advise, or how he debugs copy elision issues while developing the features.

For the second, I mentioned the Memory.Initialization module which seemed like such a way of getting control in an initialization setting. I was uncertain whether there are similar techniques (or other tricks) that could be used around argument-passing or return statements.

For a bit of context, one of the things that led to this question was that he had a procedure that originally returned an array:

proc foo() {
  var someArr: [1..n] real;
  ...
  return someArr;
}

but then at some point he decided to make it take the array in by reference, yet forgot to remove the return:

proc foo(someArr: [] real) {
  ...
  return someArr;
}

and he found that it blew up his execution time because of the return (even though he was dropping the returned array on the floor), because the compiler "had" to copy it out. (Tom, did I get that right?)

Thanks for any tips or tricks here,
-Brad

Thanks for writing this up Brad! It all sounds correct except that it's memory usage rather than execution time that I'm currently worried about. Since debugging memory usage is tricky (e.g. Slurm will just kill my job and I'm not aware of any means of detecting which part of my program caused the OOM issue...), it'd be great to have some means of reasoning when a copy of a big array will be created.

I tend to use the compiler AST logs to understand what is going on. That makes sense for me but it would absolutely be reasonable to have some kind of flag asking the compiler to show details.

I'd view this as a slightly different request from asking for extra information about copy elision from the compiler. Here I would suppose it is more useful to have some at-run-time tracing facility that prints out when you allocate an array over a certain size. (I seem to recall some discussion about tracing big allocations in Arkouda but forgot the details).

Of course, once you know a line of code is making a big allocation, maybe the request of the compiler is to answer the question, "Why is this line allocating memory"? I think a feature to answer that kind of question would probably have a different interface than one where you want to understand copy elision more generally. Certainly e.g. a way to ask the compiler to - for a particular function - print information about copy elision / init / deinit choices would allow one to reason about it, but might have a lot of other information to sift through.

We do have the ability to trace memory events larger than a specific size for this sort of purpose. See the Memory Diagnostics module, and particularly the memThreshold option. The thing that Michael is remembering w.r.t. Arkouda is that Elliot recently optimized uses of this memThreshold option to reduce some overheads significantly. Those are available on main and in the 1.25.1 release which is 3/4 out to the world.

-Brad