-
Notifications
You must be signed in to change notification settings - Fork 430
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
feat: Thread configuration prototype #2205
base: rolling
Are you sure you want to change the base?
feat: Thread configuration prototype #2205
Conversation
This is a prototype implementation of RCLCPP for discussion about the thread configuration feature to receive and apply a set of scheduling parameters for the threads controlled by the ROS 2 executor. Our basic idea is as below. 1. Implement a new class rclcpp::thread and modify rclcpp to use it. This class has the same function set as the std::thread but also additional features to control its thread attributions. 2. Modify the rcl layer to receive a set of scheduling parameters. The parameters are described in YAML format and passed via command line parameters, environment variables, or files. 3. the rclcpp reads the parameters from rcl and applies them to each thread in the thread pool. There have been some discussions about this pull request, as below. [ROS Discourse] https://discourse.ros.org/t/adding-thread-attributes-configuration-in-ros-2-framework/30701 [ROS 2 Real-Time Working Group] ros-realtime/ros-realtime.github.io#18 Signed-off-by: Shoji Morita <[email protected]>
9487724
to
66e2d64
Compare
This pull request has been mentioned on ROS Discourse. There might be relevant details there: https://discourse.ros.org/t/adding-thread-attributes-configuration-in-ros-2-framework/30701/2 |
https://build.ros2.org/job/Rpr__rclcpp__ubuntu_jammy_amd64/902/ |
This is a great feature, but I wonder if it should go somewhere else, e.g. rcpputils. |
Agree on both counts. |
@alsora, @mjcarroll I would like to confirm one thing below to reflect your point about this pull request. [Item to be confirmed] [Background] Our team is concerned that if the package dependency of |
Line 37 in f8072f2
|
Thanks for your pointing out. And sorry for my misspelling. I didn't mean rclcpp, but rcpputils, and I modified the comment above. |
I think that part of the |
That's fine, Line 39 in dab9c8a
|
|
As the other said, I think this does not belong in Adding things to help implement this in |
… on the pointing out below. ros2#2205 (comment) Signed-off-by: Shoji Morita <[email protected]>
…he pointing out below. ros2/rclcpp#2205 (comment) Signed-off-by: Shoji Morita <[email protected]>
… on the pointing out below. ros2/rclcpp#2205 (comment) Signed-off-by: Shoji Morita <[email protected]>
…he pointing out below. ros2/rclcpp#2205 (comment) Signed-off-by: Shoji Morita <[email protected]>
Thanks for your suggestion.
As you mentioned above, I've moved the proposed features from rcl and rclcpp to rcutils and rcpputils, respectively. |
Please, refer to the comment below. ros2/rclcpp#2205 (comment) Signed-off-by: Shoji Morita <[email protected]>
…ned in the DRAFT REP shared below. https://discourse.ros.org/t/adding-thread-attributes-configuration-in-ros-2-framework/30701/5 Signed-off-by: Shoji Morita <[email protected]>
std::lock_guard wait_lock{wait_mutex_}; | ||
for (; thread_id < thread_attributes_->num_attributes - 1; ++thread_id) { | ||
thread_attr.set_thread_attribute( | ||
thread_attributes_->attributes[thread_id]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Multi-Threaded Executor has multiple threads as a thread-pool to process the callbacks of new incoming messages (timers, services, etc.) in parallel. However, the Executor does not differentiate between different messages or timers. At run-time, a callback could be processed by any thread. There is no mapping of e.g. important callbacks to high priority threads possible. So, in my opinion, it would only makes sense to configure all threads with the same configuration (e.g. priority, core-affinity, ...). If at all.
What is your intention to assign different thread parameters (e.g. priority, core-affinity) to different threads?
Could you give an example how you intend to use the Multi-Threaded Executor with different thread priorities in your use-case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for your great effort to add thread configuration to ROS2. This is very important piece of work regarding real-time support. I think we need a proper way to control the thread configuration of the thread, which is processing a callback. I am not so sure, that assigning different thread-priorities to to threads of the Multi-Threaded Executor solves the problem. It is also necessary to define a mapping of callbacks (of subscriptions, timers, services, etc.) to a particular thread configuration (e.g. priority).
Alternative approaches:
-
create a thread outside ROS 2 and then let the Single-Threaded Executor run inside it.
-
the user specifies the priority per subscription. Then the Executor changes the thread priority just before the callback is called (this concept works for the Single-Threaded as well as Multi-Threaded Executor. This concept will be used in an experimental real-time executor at the "Real-time programming with ROS 2" Workshop at ROSCon. The source code will be made available.
-
extend Events-Executor to control real-time behavior.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Other approaches are to create a thread outside ROS 2 and then let e.g. the single threaded Executor run.
I agree with this.
We should not have executors modify the attributes of the thread that they are running into. If users want to run a single-threaded executor in a thread with specific attributes, they can easily do it themselves, rather than having the executor change things under their feet.
A different scenario is whenever the rclcpp library internally creates threads (e.g. the events-executor, the clock subscriptions, the graph updates etc) all these can take advantage of the new tools to configure threads (rather than just blindly inheriting the parent thread configurations).
Besides that, I'm not convinced by the use of
rcutils_thread_attrs_t * attrs = rcl_context_get_thread_attrs(options.context->get_rcl_context().get()
We shouldn't restrict to a single thread attribute per ROS context and the two concepts shouldn't be tied together.
I would recommend to have all classes that deal with threads to take a rcutils_thread_attrs_t
as input in the constructor
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think that this is the correct way to use the new thread attribute utilities.
See https://github.com/ros2/rclcpp/pull/2205/files#r1293481529 for details
There are some use cases assigning each thread to specific cores to limit the CPU usage of a particular node (e.g., a node should run on energy-efficient cores). But, as you mentioned, setting different priorities and scheduling policies for the threads is redundant and meaningless.
I agree that there are some cases like you mentioned. But still, I'm not sure if it is enough or not because there seem to be cases we should assign priorities for the event chain, not an event. I'd like to discuss this topic in the other thread.
I agree that there might be cases that require such a style. On the other hand, there seem to be some users who want to delegate such a thread creation to the executor.
So, what if we modified the implementation to create all the thread(s) the executor uses only when there are thread attributes passed to rcl, or the user application constructs the executor with thread attributes as a parameter, as I mentioned below? (Q2)
I could not understand what you meant to say above. Did you mean that we could have multiple executors per process, so we have to have multiple thread configuration sets for such cases? (Q3)
I agree with you. So, what if we modify the single/multi-thread executor to accept the thread attributes (rcutils_thread_attrs_t) and use it to set each thread attribution? (Q4) Incidentally, I'm going to implement the parameter passing mechanism above by modifying the ExecutorOption to have thread attributes configuration as below and also add a parameter overwriting method to set arbitrary thread attributes like NodeOptions.
|
TL;DR; My thoughts on Q1/Q2.
it's the first time I hear about a real need for this use-case (people really want to have ROS create threads under their feet, when they could just to it with a single line of code? If they know what a thread is and they also have interest in configuring it, then I'm sure they would be happy to have full control over it). Moreover, I would rather have an utility that creates a thread with an executor for you, rather than adding a lot of complexity to the executor class itself.
Yes, having multiple nodes and executor per process is actually a common usage and it's encouraged by the presence of ROS 2 components.
Yes, sounds good, but with some caveats. So, I would say that we could expand the executor options with the new argument, but this should be a single value (not a vector/list/map). If the executor is going to create threads internally, then it's going to use this attribute for all its internal threads. |
… infrastructure proposed in the REP-2017 below. ros-infrastructure/rep#385 Signed-off-by: Shoji Morita <[email protected]>
…ad below. ros-infrastructure/rep#385 (comment) Signed-off-by: Shoji Morita <[email protected]>
Hi @smorita-esol, what's the current status of this PR? |
This PR is based on the other PRs and REP, which are still discussed in the real-time Working group. Particularly, the REP-2017 is important to be accepted before the related PRs below get reviewed and merged. ros2/rcl#1075 While waiting for the acceptance, we might have to discuss the modification of the language binding layer (rclcpp) and/or create another REP related to this and rcpputils PR below. |
This is a prototype implementation of RCLCPP for discussion about the thread configuration feature to receive and apply a set of scheduling parameters for the threads controlled by the ROS 2 executor.
Our basic idea is as below.
There have been some discussions about this pull request, as below.
[ROS Discourse]
https://discourse.ros.org/t/adding-thread-attributes-configuration-in-ros-2-framework/30701
[ROS 2 Real-Time Working Group]
ros-realtime/ros-realtime.github.io#18