facebookexperimental / facebookexperimental/libunifex

How to parallelize producer and consumer in current stream design (maybe with buffer)?

Open
#426 4 comments 0 reactions 0 assignees View on GitHub
enhancement
Dominant language
C++
Stars
1.7k
Forks
210
PR merge metrics
No merged PRs in 30d

Description

I noticed that libunifex have additional stream design which is currently missing in P2300. However, I have no idea how to parallelize producer and consumer with the current design.

What I want:
```c++
new_thread_context thread_ctx; // used for producer for long running computational task
io_context io_ctx; // used for consumer to do some IO on values produced by producer

async_buffer buffer; // something like System.Threading.Tasks.Dataflow.BufferBlock in C#

Task<> producer() {
co_await schedule(thread_ctx.get_scheduler());
for (auto&& value: long_running_work()) {
buffer.post(value);
}
buffer.complete();
}

Task<> consumer() {
co_await schedule(io_ctx.get_scheduler());
while (auto value = co_await buffer.async_read()) {
// async IO operation need to be scheduled by io_context
co_await async_io(value);
}
}

sync_wait(when_all(producer(), consumer()));
```

While current stream design the values are produced lazily and on-demand only when the consumer asks for the next value. In this case, I must `co_await` the finish of this async io operation before I can ask the producer to compute next value, and It's a waste of time. Since the computing and io operations are scheduled on different contexts, they can be parallel actually.

```c++
auto s = some_stream();
while (auto value = co_await done_as_optional(next(s))) {
// async io operation need to be scheduled by io_context
co_await async_io(value);
}
```

By the way, here I cannot just put `async_io` to additional `async_scope` to avoid `co_await`ing, since some io operation like `AsyncWrite` in GRPC does not support calling multiple times before scheduled by the context again.

Maybe I can put `next(s)` to `async_scope`? I don't know if it's right. But if the mentioned `async_buffer` exists, the solution is handy.

Here I used coroutines to express my thoughts since it's more intuitive. Another question is how to express that without coroutine?

Thanks

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.