stan-dev / stan-dev/stanc3

Why are declarations and allocations done on different lines in write_array?

Open
#503 9 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

cpp-codegen optimization
Dominant language
OCaml
Stars
160
Forks
59
Avg merge
21h 45m
Merged PRs (30d)
26

Description

I'm looking at code like the below for write_array, log_prob, and other places we do FnReadParam

      // ex in log_prob
      stan::io::reader<local_scalar_t__> in__(params_r__, params_i__);
      //...
      Eigen::Matrix<local_scalar_t__, -1, -1> VV;
      VV = Eigen::Matrix<local_scalar_t__, -1, -1>(N, M);
      current_statement__ = 1;
      VV = in__.matrix(N, M);

Is there a reason why this is not just

Eigen::Matrix<double, -1, -1> VV = in__.matrix(N, M);

This would probably be a lot easier for the C++ compiler to optimize. For example see the godbolt link below with the example assembly output for both versions above

https://godbolt.org/z/3yqJfN (gcc)
https://godbolt.org/z/KawadE (clang)

The assembly for the way things are done now (top view, left part of diff view) has a lot more stuff than the simpler method (bottom view, right part of diff view). The current method also has to do an extra allocation and deletion.

I tried parsing out how to do the simpler method but I got lost at pp_compiler_internal_fn where the compiler does

  | Some FnReadParam -> (
    match es with
    | {Expr.Fixed.pattern= Lit (Str, base_type); _} :: dims ->
        pf ppf "@[<hov 2>in__.%s(@,%a)@]" base_type (list ~sep:comma pp_expr)
          dims

For the VV = in__.matrix(N, M);, but couldn't find where the original declaration and initialization is for

      Eigen::Matrix<double, -1, -1> VV;
      VV = Eigen::Matrix<double>(N, M);

Any pointers on where to look?

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at pp_compiler_internal_fn and trace the FnReadParam generation used by write_array and log_prob, comparing it with the declaration and assignment shown in the generated C++. Use the linked GCC and Clang Godbolt examples to verify the allocation difference. Done would mean documenting the generation path and deciding whether combining declaration and initialization is an appropriate compiler change.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp, ocaml
Domain
compilers
Issue type
Refactor
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.