adaptive_component
- A composable container for Adaptive ROS 2 Node computations.
Allows building Nodes that can select between FPGA, CPU or GPU, at run-time. Stateless by default, can be made stateful to meet use-case specific needs. Refer to examples in README.
Technically, provides A ROS 2 Node subclass programmed as a "Component" and including its own single threaded executor to build adaptive computations. Adaptive ROS 2 Nodes are able to perform computations in the CPU, the FPGA or the GPU, adaptively. Adaptive behavior is controlled through the "adaptive" ROS 2 parameter.
README
adaptive_component
A composable stateless container for Adaptive ROS 2 Node computations. Select between FPGA, CPU or GPU at run-time.
Nodes using hardware acceleration are able to perform computations faster relying on FPGAs or GPUs, improving performance. Adaptive ROS 2 Nodes leverage hardware acceleration at run-time, allowing robotics engineers to select which computational resource the Node uses on-the-go, giving roboticists a finer-grained control over the resources their computional graphs use in the underlying hardware.
This ROS 2 package provides a composable stateless container for Adaptive ROS 2 Node computations: adaptive_component
. It allows building Nodes that can select between FPGA, CPU or GPU, at run-time.
Technically, it’s a ROS 2 Node
[^1] subclass programmed as a Component
[^2] and including its own single threaded executor
to build adaptive computations. Adaptive ROS 2 Nodes
can then be built easily and are able to perform computations in the CPU, the FPGA or the GPU. Adaptive behavior is controlled through the adaptive
ROS 2 parameter, with the following values allowed:
0
: Hardware::CPU1
: Hardware::FPGA2
: Hardware::GPU
adaptive_component
is stateless by default, if you need your Adaptive Nodes to be stateful, feel free to inherit from composition::AdaptiveComponent
and create your own stateful subclasses[^5].
How does it work?
using NodeCPU = composition::DoubleVaddComponent;
using NodeFPGA = composition::DoubleVaddComponentFPGA;
rclcpp::NodeOptions options;
// Create an executor
rclcpp::executors::MultiThreadedExecutor exec;
// Create an adaptive ROS 2 Node using "components", the resulting
// Node is also programed as a "component", retaining composability
auto adaptive_node = std::make_shared<composition::AdaptiveComponent>(
"doublevadd_publisher_adaptive",
options,
// CPU
std::make_shared<NodeCPU>("_doublevadd_publisher_adaptive_cpu", options),
// FPGA
std::make_shared<NodeFPGA>("_doublevadd_publisher_adaptive_fpga", options),
// GPU
nullptr);
exec.add_node(adaptive_node); // fill up the executor
exec.spin(); // spin the executor
Then, dynamically, one could switch from CPU to FPGA by setting the adaptive
parameter in the /doublevadd_publisher_adaptive
Node:
To run in the CPU:
ros2 param set /doublevadd_publisher_adaptive adaptive 0
To run in the FPGA:
ros2 param set /doublevadd_publisher_adaptive adaptive 1
Why should I care as a ROS package maintainer?
The integration of hardware acceleration into ROS often requires rewriting parts of the Node computations to further exploit parallelism. These changes often conflict with CPU-centric architectures and as a maintainer, you’re likely to care for “not breaking” CPU-centric implementations.
To consistently integrate hardware acceleration, avoid unnecessary forks and discourage package fragmentation, composition::AdaptiveComponent
allows to extend ROS 2 CPU-centric Nodes[^3] with their computational counterparts separating concerns at build-time. From a package-maintenance perspective, each Node (across computation options) is written in a separated file and as a separated Component. These can live either within the same package, or in totally different (disconnected) ones. adaptive_component
takes care of putting them together at launch time and no dependency with the package is required at build-time[^4].
From an execution perspective, developers can easily create Adaptive ROS 2 Nodes and compose them together as desired at launch-time, with capabilities to adaptively switch between compute alternatives at run-time.
Some examples
Examples of using adaptive_component
:
Conventions and recommendations
The following conventions and recommendations are meant to facilitate the integration of hardware acceleration in existing ROS packages
Component-oriented:
AdaptiveComponent
is built as a component and should be used as such to maintain composability of Nodes.Naming: The Adaptive Node should be suffix with
_adaptive
to identify in the computational graph which Nodes have adaptive capabilities and which do not.Hidden sub-Nodes: Adaptive Node components (compute-specific ones e.g. CPU’s or FPGA’s) should be named with a hyphen (
_
) as a prefix, which will make them hidden Nodes by default.File names: When possible, source code file names should adhere to the following guidelines:
CPU-based computational Nodes can optionally add the
_cpu
suffixFPGA-based computational Nodes shall add the
_fpga
suffixGPU-based computational Nodes shall add the
_gpu
suffix
Quality Declaration
This package claims to be in the Quality Level 4 category, see the Quality Declaration for more details.