Skip to content

common/async: spawn_group and parallel_for_each()#50005

Closed
cbodley wants to merge 32 commits intoceph:wip-coro-after-reeffrom
cbodley:wip-async-parallel-for-each
Closed

common/async: spawn_group and parallel_for_each()#50005
cbodley wants to merge 32 commits intoceph:wip-coro-after-reeffrom
cbodley:wip-async-parallel-for-each

Conversation

@cbodley
Copy link
Contributor

@cbodley cbodley commented Feb 6, 2023

adds a spawn_group template class for fork-join parallelism with boost::asio::awaitable<void> coroutines, and builds a parallel_for_each() algorithm (modeled after seastar::parallel_for_each) on top

the main use for rgw multisite is where we spawn a coroutine for each log shard, then wait for all of them to complete

the existing ceph::async::co_throttle from #49720 can be used for this, but it's interface was designed for bounded concurrency, so is less convenient to use in the unbounded fork-join case: the caller has to co_await each spawn separately and handle potential errors from other coroutines. with spawn_group, errors are reported through a single co_await on the wait() member function

asio provides a generic fork-join algorithm in asio::experimental::make_parallel_group(), but it requires the group size to be known at compile time. for multisite, the shard counts are variable and come from ceph.conf

spawn_group example

awaitable<void> child(task& t);

awaitable<void> parent(std::span<task> tasks)
{
  // process all tasks in parallel
  auto ex = co_await boost::asio::this_coro::executor;
  auto group = spawn_group{ex, tasks.size()};
  for (auto& t : tasks) {
    boost::asio::co_spawn(ex, child(t), group);
  }
  co_await group.wait();
}

parallel_for_each() example

awaitable<void> child(task& t);

awaitable<void> parent(std::span<task> tasks)
{
  co_await parallel_for_each(tasks.begin(), tasks.end(), child);
}
Show available Jenkins commands
  • jenkins retest this please
  • jenkins test classic perf
  • jenkins test crimson perf
  • jenkins test signed
  • jenkins test make check
  • jenkins test make check arm64
  • jenkins test submodules
  • jenkins test dashboard
  • jenkins test dashboard cephadm
  • jenkins test api
  • jenkins test docs
  • jenkins render docs
  • jenkins test ceph-volume all
  • jenkins test ceph-volume tox
  • jenkins test windows

adamemerson and others added 23 commits February 14, 2023 12:52
Needed to fix coroutine detection under Clang

TODO: update boost package sha1 in install-deps.sh when we have
packages uploaded

Signed-off-by: Adam C. Emerson <aemerson@redhat.com>
Previously we had versions of all the calls that took an int64_t and
optional key and namespace.

This didn't really offer much benefit and doubled the maintenance
burden for changing anything.

As such just make the IOContext constructor non-explicit, and make all
its mutators return the same IOContext so people can supply them
builder-style if they want to.

Also don't wrap things in 'optional' when the underlying library
doesn't. The callers just end up having to wrap and unwrap with
value-or repeatedly.

Signed-off-by: Adam C. Emerson <aemerson@redhat.com>
This form of completion handling is compatible with C++20 Completions
and generally more flexible stuff.

Signed-off-by: Adam C. Emerson <aemerson@redhat.com>
The lock will continue to be held over the 'dispatch' with C++20
coroutines.

Signed-off-by: Adam C. Emerson <aemerson@redhat.com>
Apparently in some cases we were using references to objects on the
caller stack that happen to no longer exist if the caller's stack goes
away.

C++20 Coroutines tickled this bug.

Signed-off-by: Adam C. Emerson <aemerson@redhat.com>
Use `min` rather than `max` when deciding how much we need to read in
`read()`.

Signed-off-by: Adam C. Emerson <aemerson@redhat.com>
Just as a demonstration to see how well they work and how to put
things together with them.

Signed-off-by: Adam C. Emerson <aemerson@redhat.com>
Signed-off-by: Adam C. Emerson <aemerson@redhat.com>
Signed-off-by: Adam C. Emerson <aemerson@redhat.com>
In the `destroy_` functions of `CompletionImpl` we were getting the
associated allocator after moving out of the handler into the call to
`bind_and_forward`. This was triggering a crash on null-pointer access
in operations made with `co_composed`.

Signed-off-by: Adam C. Emerson <aemerson@redhat.com>
Since reading CLS values in a friendly way requires calling out to RADOS
then decoding the returned structure, make a function to help with that.

Signed-off-by: Adam C. Emerson <aemerson@redhat.com>
Google Test does not support C++ coroutines, so kludge together a test
harness that supports coroutines reasonably well.

Also add a couple utility functions.

Signed-off-by: Adam C. Emerson <aemerson@redhat.com>
Signed-off-by: Adam C. Emerson <aemerson@redhat.com>
Signed-off-by: Casey Bodley <cbodley@redhat.com>
Signed-off-by: Casey Bodley <cbodley@redhat.com>
…utines

Signed-off-by: Casey Bodley <cbodley@redhat.com>
We should not be using std::list everywhere, and this is an excellent
time to switch.

Signed-off-by: Adam C. Emerson <aemerson@redhat.com>
Signed-off-by: Adam C. Emerson <aemerson@redhat.com>
Signed-off-by: Adam C. Emerson <aemerson@redhat.com>
Signed-off-by: Adam C. Emerson <aemerson@redhat.com>
If our decoder function returns a tuple of multiple values, flatten it
so our signature is `void(error_code, T, U, V)` not
`void(error_code, std::tuple<T, U, V>)`.

Signed-off-by: Adam C. Emerson <aemerson@redhat.com>
And return them to the client by setting the error cod and result in
the vector and returning an error from the operation as a whole.

Signed-off-by: Adam C. Emerson <aemerson@redhat.com>
Since they can be reported now, report them

Signed-off-by: Adam C. Emerson <aemerson@redhat.com>
adamemerson and others added 6 commits February 14, 2023 12:52
Signed-off-by: Adam C. Emerson <aemerson@redhat.com>
Signed-off-by: Casey Bodley <cbodley@redhat.com>
Signed-off-by: Casey Bodley <cbodley@redhat.com>
Signed-off-by: Casey Bodley <cbodley@redhat.com>
Signed-off-by: Casey Bodley <cbodley@redhat.com>
Signed-off-by: Casey Bodley <cbodley@redhat.com>
@github-actions
Copy link

This pull request can no longer be automatically merged: a rebase is needed and changes have to be manually resolved

Signed-off-by: Casey Bodley <cbodley@redhat.com>
Signed-off-by: Casey Bodley <cbodley@redhat.com>
Signed-off-by: Casey Bodley <cbodley@redhat.com>
@github-actions
Copy link

This pull request can no longer be automatically merged: a rebase is needed and changes have to be manually resolved

@cbodley
Copy link
Contributor Author

cbodley commented Mar 1, 2023

merged into #49737

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants