NVIDIA Index example code nvidia_logo_transpbg.gif Up
cluster_rendering_remotehost.cpp
Go to the documentation of this file.
1/******************************************************************************
2 * Copyright 2023 NVIDIA Corporation. All rights reserved.
3 *****************************************************************************/
6
7#include <mi/dice.h>
8
9// Include code shared by all examples.
10#include "utility/example_shared.h"
11
12#include <nv/index/iindex.h>
13
14#include <iostream>
15#include <sstream>
16#include <map>
17#include <stdlib.h>
18
19#include "utility/app_rendering_context.h"
20
21#include <nv/index/app/forwarding_logger.h>
22#include <nv/index/app/string_dict.h>
23#include <nv/index/app/time_functions.h>
24#include <nv/index/app/index_connect_.h> // FIXME should be updated to index_connect.h
25
26namespace { // anonymous namespace for the local functions
27
28//----------------------------------------------------------------------
29// Local Index_connect for cluster_rendering_mainhost
30class Cluster_rendering_remotehost_index_connect:
31 public nv::index::app::Index_connect
32{
33public:
34 Cluster_rendering_remotehost_index_connect()
35 :
36 Index_connect()
37 {
38 // INFO_LOG << "DEBUG: Cluster_rendering_remotehost_index_connect() ctor";
39 }
40
41 virtual ~Cluster_rendering_remotehost_index_connect()
42 {
43 // Note: Index_connect::~Index_connect() will be called after here.
44 // INFO_LOG << "DEBUG: ~Cluster_rendering_remotehost_index_connect() dtor";
45 }
46
47protected:
48 // override for unittest support
49 virtual bool initialize_networking(
50 mi::neuraylib::INetwork_configuration* network_configuration,
51 nv::index::app::String_dict& options) CPP11_OVERRIDE
52 {
53 check_success(network_configuration != 0);
54
55 check_success(options.is_defined("unittest"));
56 const bool is_unittest = nv::index::app::get_bool(options.get("unittest"));
57 if (is_unittest)
58 {
59 info_cout("NETWORK: disabled networking mode.", options);
60 network_configuration->set_mode(mi::neuraylib::INetwork_configuration::MODE_OFF);
61 }
62
63 return initialize_networking_as_default_udp(network_configuration, options);
64 }
65
66 // override
67 virtual bool register_serializable_classes(
68 mi::neuraylib::IDice_configuration* configuration_interface,
69 nv::index::app::String_dict& options) CPP11_OVERRIDE
70 {
71 // bool is_registered = false;
72 // is_registered = get_index_interface()->register_serializable_class<Arrow_manipulator>();
73 // check_success(is_registered);
74 // return is_registered;
75 return true;
76 }
77
78 // override
79 virtual bool initialize_debug_configuration(
80 mi::neuraylib::IDebug_configuration* debug_configuration,
81 nv::index::app::String_dict& options) CPP11_OVERRIDE
82 {
83 check_success(debug_configuration != 0);
84 if (options.is_defined("dice::idebug_config::retention"))
85 {
86 bool conv_stat = false;
87 const std::string retension = options.get("dice::idebug_config::retention");
88 const mi::Sint32 debug_retention = nv::index::app::get_sint32(retension, &conv_stat);
89 if (!conv_stat)
90 {
91 ERROR_LOG << "initialize_index_debug_configuration: failed integer conversion of dice::idebug_config::retention: "
92 << debug_retention;
93 return false;
94 }
95
96 if(debug_retention > 0)
97 {
98 std::stringstream sstr;
99 sstr << "retention=" << debug_retention;
100 debug_configuration->set_option(sstr.str().c_str());
101 INFO_LOG << "Set IDebug_configuration: " << sstr.str();
102 }
103 }
104
105 return true;
106 }
107
108 // override
109 virtual bool initialize_general_configuration(
110 mi::neuraylib::IGeneral_configuration* general_configuration,
111 nv::index::app::String_dict& options) CPP11_OVERRIDE
112 {
113 check_success(general_configuration != 0);
114 general_configuration->set_host_property("sub_cluster_id", "0"); // set default cluster id 0
115 return true;
116 }
117};
118
119//----------------------------------------------------------------------
120// Remote rendering loop
121//
122// \param[in] nvindex_accessor nvindex accessor
123// \param[in] arc application rendering context
124// \param[in] opt_map command line option map
125// \return true when success
126bool remote_rendering_loop(
127 Cluster_rendering_remotehost_index_connect& index_connect,
128 App_rendering_context& arc,
129 nv::index::app::String_dict& sdict)
130{
131 mi::base::Handle<nv::index::ICluster_configuration> rendering_properties_query(
132 index_connect.get_index_interface()->get_api_component<nv::index::ICluster_configuration>());
133 check_success(rendering_properties_query.is_valid_interface());
134
135 mi::Uint32 number_of_hosts = rendering_properties_query->get_number_of_hosts();
136
137 std::stringstream sstr;
138 sstr << "**********************************************************************\n"
139 << "info: NVIDIA IndeX remote service running and waiting for connections,\n"
140 << "info: Cluster host id = " << rendering_properties_query->get_local_host_id() << "\n"
141 << "info: ****************************************************************";
142 INFO_LOG << sstr.str();
143
144 check_success(sdict.is_defined("unittest"));
145
146 const bool is_unittest = nv::index::app::get_bool(sdict.get("unittest", "false"));
147 const mi::Sint32 remote_max_iter_when_unittest = 8;
148
149 for(mi::Sint32 i = 0; true; ++i)
150 {
151 const mi::Uint32 new_number_of_hosts = rendering_properties_query->get_number_of_hosts();
152
153 // Finish on lost host
154 if (new_number_of_hosts < number_of_hosts)
155 {
156 std::stringstream sstr;
157 sstr << "Leaving the NVIDIA IndeX remote service loop because at least one other cluster host has left. "
158 << "Previously, the cluster was composed by "
159 << number_of_hosts << " hosts. Now, only "
160 << new_number_of_hosts << " cluster hosts are left.";
161 INFO_LOG << sstr.str();
162
163 break;
164 }
165
166 // exit if unittest mode with max iters
167 if (is_unittest&& (i>= remote_max_iter_when_unittest))
168 {
169 INFO_LOG << "The unit test exits because the test has reached the maximum number of iterations.";
170
171 break;
172 }
173
174 number_of_hosts = new_number_of_hosts;
175 nv::index::app::util::time::sleep(0.1f); // wait for 0.1 second
176 }
177
178 INFO_LOG << "Finished the NVIDIA IndeX remote service loop.";
179
180 return true;
181}
182
183//----------------------------------------------------------------------
184// set up as a remote host
185//
186// \param[in] nvindex_accessor nvindex library accessor
187// \param[in,out] arc application rendering context
188// \return true when success
189bool setup_remote_host(
190 Cluster_rendering_remotehost_index_connect& index_connect,
191 App_rendering_context& arc)
192{
193 arc.m_database = index_connect.get_index_interface()->get_api_component<mi::neuraylib::IDatabase>();
194 check_success(arc.m_database.is_valid_interface());
195
196 arc.m_global_scope = arc.m_database->get_global_scope();
197 check_success(arc.m_global_scope.is_valid_interface());
198
199 return true;
200}
201
202//----------------------------------------------------------------------
203// network parameters
204//
205// \param[in,out] nvindex_accessor nvindex library accessor
206// \param[in] opt_map command line option map
207void config_network_parameters(
208 Cluster_rendering_remotehost_index_connect& index_connect,
209 nv::index::app::String_dict& sdict)
210{
211 if (sdict.get("dice::network::additional_unicast_sockets", "0") != "0")
212 {
213 mi::base::Handle<mi::neuraylib::IDebug_configuration> debug_configuration(
214 index_connect.get_index_interface()->get_api_component<mi::neuraylib::IDebug_configuration>());
215 check_success(debug_configuration.is_valid_interface());
216
217 std::stringstream sstr;
218 sstr << "dice::network::additional_unicast_sockets="
219 << sdict.get("dice::network::additional_unicast_sockets", "<undef>");
220 const std::string additional_unicast_sockets = sstr.str();
221 debug_configuration->set_option(additional_unicast_sockets.c_str());
222 }
223}
224
225} // namespace anonymous
226
227//----------------------------------------------------------------------
228// main routine for the remote host
229int main(int argc, char* argv[])
230{
231 const std::string com_name(argv[0]);
232 nv::index::app::String_dict sdict;
233 sdict.insert("dice::verbose", "3"); // log level
234 sdict.insert("dice::network::mode", "UDP"); // network mode
235 sdict.insert("dice::network::multicast_address", "239.43.1.1"); // multicast address
236 sdict.insert("dice::network::additional_unicast_sockets", "0"); // default number of unicast sockets
237 sdict.insert("unittest", "0"); // default mode
238 sdict.insert("dice::idebug_config::retention", "0"); // retention
239 sdict.insert("is_dump_comparison_image_when_failed", "1"); // default: dump images when failed.
240 sdict.insert("is_call_from_test", "0"); // default: not call from make check.
241
242 Cluster_rendering_remotehost_index_connect index_connect;
243 index_connect.process_command_line_arguments(argc, argv, sdict);
244
245 if (nv::index::app::get_bool(sdict.get("unittest", "false")))
246 {
247 // try to randomize the multicast address for the test purpose. This does not guarantee, but practically fine.
248 mi::Uint32 cur_time = static_cast<mi::Uint32>(nv::index::app::util::time::get_time() * 10000);
249 srand(cur_time);
250 mi::Sint64 r1 = (rand() % 254) + 1;
251 mi::Sint64 r2 = (rand() % 254) + 1;
252 std::stringstream sstr;
253 sstr << "239.43." << r1 << "." << r2;
254 std::string mc_addr = sstr.str();
255
256 std::stringstream sstr2;
257 sstr2 << "Cur_time: " << cur_time << ", Using multicast address: " << mc_addr;
258 info_cout(sstr2.str(), sdict);
259
260 sdict.insert("dice::network::multicast_address", mc_addr);
261
262 if (nv::index::app::get_bool(sdict.get("is_call_from_test", "false")))
263 {
264 sdict.insert("is_dump_comparison_image_when_failed", "0");
265 }
266 sdict.get("dice::verbose", "2");
267 }
268 info_cout("running " + com_name, sdict);
269 info_cout("dice::verbose = " + sdict.get("dice::verbose"), sdict);
270
271 // print help and exit if -h/-help
272 if (sdict.is_defined("h") || sdict.is_defined("help"))
273 {
274 std::cout
275 << "info: Usage: " << com_name << " [option]\n"
276 << "Option: [-h]\n"
277 << " printout this message\n"
278
279 << " [-dice::verbose severity_level]\n"
280 << " verbose severity level (3 is info.).\n"
281 << " (default: " + sdict.get("dice::verbose", "<undef>") + ")\n"
282
283 << " [-dice::network::multicast_address address]\n"
284 << " set multicast address.\n"
285 << " (default: " << sdict.get("dice::network::multicast_address", "<undef>") << ")\n"
286
287 << " [-dice::network::additional_unicast_sockets int]\n"
288 << " set number of unicast sockets for remote host.\n"
289 << " (default: " << sdict.get("dice::network::additional_unicast_sockets", "<undef>") << ").\n"
290
291 << " [-unittest bool]\n"
292 << " when test true, unit test mode.\n"
293 << " (default: " << sdict.get("unittest", "<undef>") << ")"
294
295 << " [-dice::idebug_config::retention int]\n"
296 << " when set, set this idebug configuration option. not set when 0.\n"
297 << " (default: " << sdict.get("dice::idebug_config::retention", "<undef>") << ")"
298 << std::endl;
299 exit(1);
300 }
301
302 // index setting
303 sdict.insert("index::config::set_monitor_performance_values", "true");
304 sdict.insert("index::service", "rendering_and_compositing");
305 sdict.insert("index::cuda_debug_checks", "false");
306
307 // application_layer component loading
308 sdict.insert("index::app::components::application_layer::component_name_list",
309 "canvas_infrastructure data_analysis_and_processing image io");
310 // plugin: base_importer
311 sdict.insert("index::app::plugins::base_importer::enabled", "true");
312
313 // set network parameters for DiCE
314 {
315 config_network_parameters(index_connect, sdict);
316 }
317
318 info_cout(std::string("start IndeX via index_connect"), sdict);
319 index_connect.initialize(sdict);
320 check_success(index_connect.is_initialized());
321
322 // setup
323 App_rendering_context arc;
324 check_success(setup_remote_host(index_connect, arc));
325
326 // call remote rendering loop
327 remote_rendering_loop(index_connect, arc, sdict);
328
329 printf("Shutting down the NVIDIA IndeX library.\n");
330 arc.shutdown();
331 // index_connect will shutdown when out of scope
332
333 printf("Terminating the NVIDIA IndeX remote service.\n");
334 return 0;
335}
int main(int argc, char *argv[])
#define check_success(expr)