Skip to content

Commit c25de90

Browse files
committed
Enable Data Flow Tracking
Signed-off-by: Victor Chang <[email protected]>
1 parent f1cdff4 commit c25de90

File tree

14 files changed

+195
-21
lines changed

14 files changed

+195
-21
lines changed

applications/distributed/grpc/grpc_endoscopy_tool_tracking/CMakeLists.txt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,20 @@
1616
cmake_minimum_required(VERSION 3.20)
1717
project(grpc_endoscopy_tool_tracking LANGUAGES NONE)
1818

19+
# Download the endoscopy sample data
20+
if(HOLOHUB_DOWNLOAD_DATASETS)
21+
include(holoscan_download_data)
22+
holoscan_download_data(endoscopy
23+
URL https://api.ngc.nvidia.com/v2/resources/nvidia/clara-holoscan/holoscan_endoscopy_sample_data/versions/20230222/zip
24+
DOWNLOAD_NAME holoscan_endoscopy_sample_data_20230222.zip
25+
URL_MD5 d54f84a562d29ed560a87d2607eba973
26+
DOWNLOAD_DIR ${HOLOHUB_DATA_DIR}
27+
GENERATE_GXF_ENTITIES
28+
GXF_ENTITIES_HEIGHT 480
29+
GXF_ENTITIES_WIDTH 854
30+
GXF_ENTITIES_CHANNELS 3
31+
GXF_ENTITIES_FRAMERATE 30
32+
)
33+
endif()
34+
1935
add_subdirectory(cpp)

applications/distributed/grpc/grpc_endoscopy_tool_tracking/README.md

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,76 @@ The data is automatically downloaded when building the application.
3535

3636
* Building and running the application from the top level Holohub directory:
3737

38+
39+
### Configuration
40+
41+
The Edge application runs in a single-fragment mode by default. However, it can be configured to run in a mult-fragment mode, as in the picture above.
42+
43+
To switch to multi-fragment mode, edit the [endoscopy_tool_tracking.yaml](./cpp/endoscopy_tool_tracking.yaml) YAML file and change `multifragment` to `true`.
44+
45+
```yaml
46+
47+
application:
48+
multifragment: false
49+
benchmarking: false
50+
```
51+
52+
[Data Flow Tracking](https://docs.nvidia.com/holoscan/sdk-user-guide/flow_tracking.html) can also be enabled by editing the [endoscopy_tool_tracking.yaml](./cpp/endoscopy_tool_tracking.yaml) YAML file and change `benchmarking` to `true`. This enables the built-in mechanism to profile the application and analyze the fine-grained timing properties and data flow between operators.
53+
54+
For example, on the server side, when a client disconnects, it will output the results for that session:
55+
56+
```bash
57+
Data Flow Tracking Results:
58+
Total paths: 1
59+
60+
Path 1: grpc_request_op,format_converter,lstm_inferer,tool_tracking_postprocessor,grpc_response_op
61+
Number of messages: 663
62+
Min Latency Message No: 249
63+
Min end-to-end Latency (ms): 1.868
64+
Avg end-to-end Latency (ms): 2.15161
65+
Max Latency Message No: 371
66+
Max end-to-end Latency (ms): 4.19
67+
68+
Number of source messages [format: source operator->transmitter name: number of messages]:
69+
grpc_request_op->output: 683
70+
```
71+
72+
Similarly, on the client side, when it completes playing the video, it will print the results:
73+
74+
```bash
75+
Data Flow Tracking Results:
76+
Total paths: 3
77+
78+
Path 1: incoming_responses,visualizer_op
79+
Number of messages: 663
80+
Min Latency Message No: 249
81+
Min end-to-end Latency (ms): 0.214
82+
Avg end-to-end Latency (ms): 0.374005
83+
Max Latency Message No: 378
84+
Max end-to-end Latency (ms): 2.751
85+
86+
Path 2: replayer,outgoing_requests
87+
Number of messages: 663
88+
Min Latency Message No: 379
89+
Min end-to-end Latency (ms): 24.854
90+
Avg end-to-end Latency (ms): 27.1886
91+
Max Latency Message No: 142
92+
Max end-to-end Latency (ms): 28.003
93+
94+
Path 3: replayer,visualizer_op
95+
Number of messages: 663
96+
Min Latency Message No: 372
97+
Min end-to-end Latency (ms): 30.966
98+
Avg end-to-end Latency (ms): 33.325
99+
Max Latency Message No: 397
100+
Max end-to-end Latency (ms): 35.479
101+
102+
Number of source messages [format: source operator->transmitter name: number of messages]:
103+
incoming_responses->output: 683
104+
replayer->output: 683
105+
```
106+
107+
38108
### C++
39109

40110
```bash

applications/distributed/grpc/grpc_endoscopy_tool_tracking/cpp/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ add_executable(grpc_endoscopy_tool_tracking_cloud
2727

2828
add_executable(grpc_endoscopy_tool_tracking_edge
2929
edge/app_edge_main.cpp
30-
edge/app_edge.hpp
30+
edge/app_edge_single_fragment.hpp
31+
edge/app_edge_multi_fragment.hpp
3132
edge/video_input_fragment.hpp
3233
edge/viz_fragment.hpp
3334
)

applications/distributed/grpc/grpc_endoscopy_tool_tracking/cpp/cloud/app_cloud_main.cpp

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,21 @@ void signal_handler(int signum) {
7070
myThread.join();
7171
}
7272

73+
/** Helper function to parse benchmarking setting from the configuration file */
74+
void parse_config(const std::string& config_path, bool& benchmarking) {
75+
auto config = holoscan::Config(config_path);
76+
auto& yaml_nodes = config.yaml_nodes();
77+
for (const auto& yaml_node : yaml_nodes) {
78+
try {
79+
auto application = yaml_node["application"];
80+
if (application.IsMap()) { benchmarking = application["benchmarking"].as<bool>(); }
81+
} catch (std::exception& e) {
82+
HOLOSCAN_LOG_ERROR("Error parsing configuration file: {}", e.what());
83+
benchmarking = false;
84+
}
85+
}
86+
}
87+
7388
/** Main function */
7489
/**
7590
* @file app_cloud_main.cpp
@@ -127,12 +142,15 @@ int main(int argc, char** argv) {
127142
}
128143
}
129144

145+
bool benchmarking = false;
146+
parse_config(config_path, benchmarking);
147+
130148
// Register each gRPC service with a Holoscan application:
131149
// - the callback function (create_application_instance_func) is used to create a new instance of
132150
// the application when a new RPC call is received.
133151
ApplicationFactory::get_instance()->register_application(
134152
"EntityStream",
135-
[config_path, data_directory](
153+
[config_path, data_directory, benchmarking](
136154
std::queue<std::shared_ptr<nvidia::gxf::Entity>> incoming_request_queue,
137155
std::queue<std::shared_ptr<EntityResponse>>
138156
outgoing_response_queue) {
@@ -141,6 +159,7 @@ int main(int argc, char** argv) {
141159
incoming_request_queue, outgoing_response_queue);
142160
application_instance.instance->config(config_path);
143161
application_instance.instance->set_data_path(data_directory);
162+
if (benchmarking) { application_instance.tracker = &application_instance.instance->track(); }
144163
application_instance.future = application_instance.instance->run_async();
145164
return application_instance;
146165
});

applications/distributed/grpc/grpc_endoscopy_tool_tracking/cpp/cloud/grpc_service.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515
* limitations under the License.
1616
*/
1717

18-
#ifndef GRPC_H264_ENDOSCOPY_TOOL_TRACKING_CPP_CLOUD_GRPC_SERVICE_HPP
19-
#define GRPC_H264_ENDOSCOPY_TOOL_TRACKING_CPP_CLOUD_GRPC_SERVICE_HPP
18+
#ifndef GRPC_GRPC_ENDOSCOPY_TOOL_TRACKING_CPP_CLOUD_GRPC_SERVICE_HPP
19+
#define GRPC_GRPC_ENDOSCOPY_TOOL_TRACKING_CPP_CLOUD_GRPC_SERVICE_HPP
2020

2121
#include <fmt/format.h>
2222
#include <holoscan/holoscan.hpp>
@@ -102,4 +102,4 @@ class GrpcService {
102102
};
103103
} // namespace holohub::grpc_h264_endoscopy_tool_tracking
104104

105-
#endif /* GRPC_H264_ENDOSCOPY_TOOL_TRACKING_CPP_CLOUD_GRPC_SERVICE_HPP */
105+
#endif /* GRPC_GRPC_ENDOSCOPY_TOOL_TRACKING_CPP_CLOUD_GRPC_SERVICE_HPP */

applications/distributed/grpc/grpc_endoscopy_tool_tracking/cpp/edge/app_edge_main.cpp

Lines changed: 63 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
#include "app_edge_single_fragment.hpp"
2626

2727
// Run the edge app with two fragments
28-
// #include "app_edge.hpp"
28+
#include "app_edge_multi_fragment.hpp"
2929

3030
using namespace holoscan;
3131
using namespace holohub::grpc_h264_endoscopy_tool_tracking;
@@ -55,6 +55,25 @@ bool parse_arguments(int argc, char** argv, std::string& data_path, std::string&
5555
return true;
5656
}
5757

58+
/** Helper function to parse fragment mode and benchmarking settings from the configuration file */
59+
void parse_config(const std::string& config_path, bool& multi_fragment_mode, bool& benchmarking) {
60+
auto config = holoscan::Config(config_path);
61+
auto& yaml_nodes = config.yaml_nodes();
62+
for (const auto& yaml_node : yaml_nodes) {
63+
try {
64+
auto application = yaml_node["application"];
65+
if (application.IsMap()) {
66+
multi_fragment_mode = application["multifragment"].as<bool>();
67+
benchmarking = application["benchmarking"].as<bool>();
68+
}
69+
} catch (std::exception& e) {
70+
HOLOSCAN_LOG_ERROR("Error parsing configuration file: {}", e.what());
71+
multi_fragment_mode = false;
72+
benchmarking = false;
73+
}
74+
}
75+
}
76+
5877
/** Main function */
5978
/**
6079
* @file app_edge_main.cpp
@@ -110,13 +129,50 @@ int main(int argc, char** argv) {
110129
}
111130
}
112131

113-
auto app = holoscan::make_application<AppEdge>();
132+
bool multi_fragment_mode = false;
133+
bool benchmarking = false;
134+
parse_config(config_path, multi_fragment_mode, benchmarking);
135+
if (multi_fragment_mode) {
136+
HOLOSCAN_LOG_INFO("Running application in multi-fragment mode");
137+
auto app = holoscan::make_application<AppEdgeMultiFragment>();
138+
139+
HOLOSCAN_LOG_INFO("Using configuration file from {}", config_path);
140+
app->config(config_path);
141+
142+
HOLOSCAN_LOG_INFO("Using input data from {}", data_directory);
143+
app->set_datapath(data_directory);
144+
145+
std::unordered_map<std::string, DataFlowTracker*> trackers;
146+
if (benchmarking) {
147+
HOLOSCAN_LOG_INFO("Benchmarking enabled");
148+
trackers = app->track_distributed();
149+
}
150+
151+
app->run();
152+
153+
if (benchmarking) {
154+
for (const auto& [name, tracker] : trackers) {
155+
std::cout << "Fragment: " << name << std::endl;
156+
tracker->print();
157+
}
158+
}
159+
} else {
160+
HOLOSCAN_LOG_INFO("Running application in single fragment mode");
161+
auto app = holoscan::make_application<AppEdgeSingleFragment>();
162+
163+
HOLOSCAN_LOG_INFO("Using configuration file from {}", config_path);
164+
app->config(config_path);
114165

115-
HOLOSCAN_LOG_INFO("Using configuration file from {}", config_path);
116-
app->config(config_path);
166+
HOLOSCAN_LOG_INFO("Using input data from {}", data_directory);
167+
app->set_datapath(data_directory);
117168

118-
HOLOSCAN_LOG_INFO("Using input data from {}", data_directory);
119-
app->set_datapath(data_directory);
120-
app->run();
169+
DataFlowTracker* tracker = nullptr;
170+
if (benchmarking) {
171+
HOLOSCAN_LOG_INFO("Benchmarking enabled");
172+
tracker = &app->track();
173+
}
174+
app->run();
175+
if (benchmarking) { tracker->print(); }
176+
}
121177
return 0;
122178
}

applications/distributed/grpc/grpc_endoscopy_tool_tracking/cpp/edge/app_edge.hpp renamed to applications/distributed/grpc/grpc_endoscopy_tool_tracking/cpp/edge/app_edge_multi_fragment.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ namespace holohub::grpc_h264_endoscopy_tool_tracking {
3030
using namespace holoscan;
3131

3232
/**
33-
* @class AppEdge
33+
* @class AppEdgeMultiFragment
3434
* @brief A two-fragment application for the H.264 endoscopy tool tracking application.
3535
*
3636
* This class inherits from the holoscan::Application and is a client application offloads the
@@ -39,9 +39,9 @@ using namespace holoscan;
3939
* two systems, separating the input from the visualization. For example, a video surveillance
4040
* camera capturing and streaming input to another system displaying the footage.
4141
*/
42-
class AppEdge : public holoscan::Application {
42+
class AppEdgeMultiFragment : public holoscan::Application {
4343
public:
44-
explicit AppEdge(const std::vector<std::string>& argv = {}) : Application(argv) {}
44+
explicit AppEdgeMultiFragment(const std::vector<std::string>& argv = {}) : Application(argv) {}
4545
void set_datapath(const std::string& path) { datapath_ = path; }
4646

4747
void compose() {

applications/distributed/grpc/grpc_endoscopy_tool_tracking/cpp/edge/app_edge_single_fragment.hpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ namespace holohub::grpc_h264_endoscopy_tool_tracking {
3131
using namespace holoscan;
3232

3333
/**
34-
* @class AppEdge
34+
* @class AppEdgeSingleFragment
3535
* @brief A two-fragment application for the H.264 endoscopy tool tracking application.
3636
*
3737
* This class inherits from the holoscan::Application and is a client application offloads the
@@ -40,10 +40,10 @@ using namespace holoscan;
4040
* on two systems, separating the input from the visualization. For example, a video surveillance
4141
* camera capturing and streaming input to another system displaying the footage.
4242
*/
43-
class AppEdge : public holoscan::Application {
43+
class AppEdgeSingleFragment : public holoscan::Application {
4444
public:
45-
explicit AppEdge(const std::vector<std::string>& argv = {}) : Application(argv) {}
46-
~AppEdge() {
45+
explicit AppEdgeSingleFragment(const std::vector<std::string>& argv = {}) : Application(argv) {}
46+
~AppEdgeSingleFragment() {
4747
entity_client_service_->stop_entity_stream();
4848
}
4949

applications/distributed/grpc/grpc_endoscopy_tool_tracking/cpp/endoscopy_tool_tracking.yaml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,19 @@
1717
extensions:
1818
- ../../../../../lib/gxf_extensions/libgxf_lstm_tensor_rt_inference.so
1919

20+
application:
21+
title: Endoscopy Tool Tracking - gRPC
22+
version: 1.0
23+
inputFormats: []
24+
outputFormats: ["screen"]
25+
multifragment: false # default: false, true to run in multi-fragment mode, false otherwise
26+
benchmarking: false # default: false, true to enable Data Flow Benchmarking, false otherwise
27+
2028
replayer:
2129
basename: "surgical_video"
2230
frame_rate: 0 # as specified in timestamps
2331
repeat: false # default: false
24-
realtime: false # default: true
32+
realtime: true # default: true
2533
count: 0 # default: 0 (no frame count restriction)
2634

2735
format_converter:

applications/distributed/grpc/grpc_h264_endoscopy_tool_tracking/cpp/edge/video_input_fragment.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ class VideoInputFragment : public holoscan::Fragment {
119119
entity_client_service_ = std::make_shared<EntityClientService>(
120120
from_config("grpc_client.server_address").as<std::string>(),
121121
from_config("grpc_client.rpc_timeout").as<uint32_t>(),
122+
from_config("grpc_client.interrupt").as<bool>(),
122123
request_queue_,
123124
response_queue_,
124125
outgoing_requests);

0 commit comments

Comments
 (0)