NVIDIA / NVIDIA/stdexec

Operation state cooperation that goes through uncustomized sender layers (sort of forwarding environment)

Open
#1,802 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement
Dominant language
C++
Stars
2.4k
Forks
270
Avg merge
3d 6h
Merged PRs (30d)
39

Description

We are currently working (with @maartenarnst) on a customization for a scheduler that builds a Kokkos::Experimental::Graph under the hood.

To add a node to a Kokkos::Experimental::Graph, we need to know its predecessor(s).

Here’s an example of a diamond-shaped Kokkos::Experimental::Graph:

auto root = graph.get_root();

auto A = root.then(...);

auto B = A.then(...);
auto C = A.then(...);

auto D = Kokkos::Experimental::when_all(std::move(B), std::move(C)).then(...);

Conceptually, we’d like this to naturally translate to something like the following using exec::fork_join:

stdexec::sync_wait(
    stdexec::schedule(graph_scheduler)
    | then(...A...)
    | exec::fork_join(
          stdexec::on(graph_scheduler, ...B...),
          stdexec::on(graph_scheduler, ...C...))
    | then(...D...)
);

As mentioned, we need the predecessor(s) in order to add a new node to the graph. We create the node in the operation state.

We have already customized when_all, but we are now running into what feels like a limitation (or at least an awkward spot — or something I'm missing) in the std::execution framework:

There is no built-in mechanism to propagate information from inner to outer operation states.

In our example, A is the innermost node. How would B or C query the node created by A? Obviously (?), this cannot be done through the receiver’s environment, which only propagates information upstream from B/C to A.

Currently, we rely on the fact that the operation states of our customizations provide a get_node() member function. However, this approach breaks when exec::fork_join introduces intermediate layers between A and B/C, because those intermediate layers hide the underlying operation states.

One potential solution would be to make exec::fork_join itself customizable to forward this information. But we feel like the problem could be more general than just ours, so we wonder how more experienced people would handle it 😉

Any suggestion is appreciated !

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 by reading the operation-state and receiver-environment behavior involved in customized when_all and exec::fork_join, including how intermediate layers hide get_node(). Compare the diamond-shaped Graph example with the fork_join example; done requires an agreed, general mechanism for accessing predecessor state through forwarding layers.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
backend
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
20/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.