Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[try_put_and_wait] Part 2: Add implementation of try_put_and_wait feature for buffering nodes #1412

Conversation

kboyarinov
Copy link
Contributor

Description

Extend buffer_node, queue_node, priority_queue_node and sequencer_node interfaces with the new try_put_and_wait API for waiting on single messages.

Fixes # - issue number(s) if exists

Type of change

Choose one or multiple, leave empty if none of the other choices apply

Add a respective label(s) to PR if you have permissions

  • bug fix - change that fixes an issue
  • new feature - change that adds functionality
  • tests - change in tests
  • infrastructure - change in infrastructure and CI
  • documentation - documentation update

Tests

  • added - required for new features and some bug fixes
  • not needed

Documentation

  • updated in # - add PR number
  • needs to be updated
  • not needed

Breaks backward compatibility

  • Yes
  • No
  • Unknown

Notify the following users

List users with @ to send notifications

Other information

@kboyarinov kboyarinov changed the title [try_put_and_wait] Add implementation of try_put_and_wait feature for buffering nodes [try_put_and_wait] Part 2: Add implementation of try_put_and_wait feature for buffering nodes Jun 20, 2024
@kboyarinov kboyarinov force-pushed the dev/kboyarinov/try_put_and_wait_buffering_nodes branch from 50d92c0 to ae591d5 Compare June 21, 2024 11:01
@kboyarinov kboyarinov force-pushed the dev/kboyarinov/try_put_and_wait_buffering_nodes branch from eb18ebe to 811b9b9 Compare June 25, 2024 14:35
include/oneapi/tbb/detail/_flow_graph_cache_impl.h Outdated Show resolved Hide resolved
Comment on lines 140 to 148
bool get_item( output_type& v ) {
return get_item_impl(v);
}

#if __TBB_PREVIEW_FLOW_GRAPH_TRY_PUT_AND_WAIT
bool get_item( output_type& v, message_metainfo& metainfo ) {
return get_item_impl(v, &metainfo);
}
#endif
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it make sense to make it a single method as get_item_impl? (may be for consistency)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure I understood correctly. get_item should be considered a public API for a cache. get_item_impl - as a private method. We need to keep the existing public API get_item(v) and add a new one get_item(v, metainfo) and implement both of them on top of get_item_impl.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose for try_put_task, there are calls like try_put_task_impl(t __TBB_FLOW_GRAPH_METAINFO_ARG(message_metainfo{})). But for get_item, you'd need to create a temporary that is just dropped. While for try_put_task you still want to send the empty metainfo. Is this the reason there are two get_item_impl functions instead of something like the single try_put_task_impl function?

include/oneapi/tbb/detail/_flow_graph_impl.h Show resolved Hide resolved
include/oneapi/tbb/detail/_flow_graph_node_impl.h Outdated Show resolved Hide resolved
include/oneapi/tbb/flow_graph.h Outdated Show resolved Hide resolved
include/oneapi/tbb/flow_graph.h Outdated Show resolved Hide resolved
include/oneapi/tbb/flow_graph.h Outdated Show resolved Hide resolved
include/oneapi/tbb/flow_graph.h Outdated Show resolved Hide resolved
Comment on lines 140 to 148
bool get_item( output_type& v ) {
return get_item_impl(v);
}

#if __TBB_PREVIEW_FLOW_GRAPH_TRY_PUT_AND_WAIT
bool get_item( output_type& v, message_metainfo& metainfo ) {
return get_item_impl(v, &metainfo);
}
#endif
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose for try_put_task, there are calls like try_put_task_impl(t __TBB_FLOW_GRAPH_METAINFO_ARG(message_metainfo{})). But for get_item, you'd need to create a temporary that is just dropped. While for try_put_task you still want to send the empty metainfo. Is this the reason there are two get_item_impl functions instead of something like the single try_put_task_impl function?

include/oneapi/tbb/detail/_flow_graph_cache_impl.h Outdated Show resolved Hide resolved
Base automatically changed from dev/kboyarinov/try_put_and_wait_function_node to dev/kboyarinov/try_put_and_wait_production August 1, 2024 13:56
…production' into dev/kboyarinov/try_put_and_wait_buffering_nodes
Copy link
Contributor

@vossmjp vossmjp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks ok. One optional change, and eventually we need more concurrent tests.

Args... args)
{
std::size_t after_try_put_and_wait_start_index = 0;
tbb::task_arena arena(1);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that all of the tests are ultimately completely serial. The function_node is serial but also the flow graph executes in an arena with a single slot. I suppose this is done to make the results deterministic since most of the tests are whitebox tests that know the exact processing order. Is there risk that serial execution could hide some bugs caused by concurrency?

#if __TBB_PREVIEW_FLOW_GRAPH_TRY_PUT_AND_WAIT
void fetch_item(size_t i, item_type& o, message_metainfo& metainfo) {
__TBB_ASSERT(my_item_valid(i), "Trying to fetch an empty slot");
o = get_my_item(i); // could have std::move assign semantics
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When __TBB_PREVIEW_FLOW_GRAPH_TRY_PUT_AND_WAIT is defined, is the other overload of this function ever called? I could only find one use in flow_graph.h and it used the _ARG macro. I suppose you could have #if - #else if that's true. Seems like you only need one function or the other, never both.

Copy link
Contributor

@aleksei-fedotov aleksei-fedotov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me.

#if __TBB_PREVIEW_FLOW_GRAPH_TRY_PUT_AND_WAIT
buffer_operation(const T& e, op_type t, const message_metainfo& info)
: type(char(t)), elem(const_cast<T*>(&e)), ltask(nullptr), r(nullptr)
, metainfo(const_cast<message_metainfo*>(&info))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Such pattern of const-casting can lead to dangling references. Can we accept message_metainfo without cv-qualifiers in the first place?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since metainfo is taken as constant reference in try_put_task virtual method, we will still need to const_cast it somewhere to store it into the buffer_operation. So I would prefer to keep all casts in one class.

@kboyarinov kboyarinov merged commit 5cd159a into dev/kboyarinov/try_put_and_wait_production Aug 15, 2024
21 of 22 checks passed
@kboyarinov kboyarinov deleted the dev/kboyarinov/try_put_and_wait_buffering_nodes branch August 15, 2024 12:38
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.

4 participants