examples: Add layers group command line parameter
[tidl/tidl-api.git] / examples / test / multiple_executors.cpp
1 /******************************************************************************
2  * Copyright (c) 2018, Texas Instruments Incorporated - http://www.ti.com/
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *     * Redistributions of source code must retain the above copyright
8  *       notice, this list of conditions and the following disclaimer.
9  *     * Redistributions in binary form must reproduce the above copyright
10  *       notice, this list of conditions and the following disclaimer in the
11  *       documentation and/or other materials provided with the distribution.
12  *     * Neither the name of Texas Instruments Incorporated nor the
13  *       names of its contributors may be used to endorse or promote products
14  *       derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26  * THE POSSIBILITY OF SUCH DAMAGE.
27  *****************************************************************************/
29 //! @file multiple_executors.cpp
30 //! Illustrates how to setup multiple Executor instances using
31 //! non-overlapping sets of device ids and running the Executor instances
32 //! in parallel - each in its own thread
34 #include <signal.h>
35 #include <getopt.h>
36 #include <iostream>
37 #include <fstream>
38 #include <cassert>
39 #include <string>
40 #include <functional>
41 #include <algorithm>
42 #include <pthread.h>
44 #include "executor.h"
45 #include "execution_object.h"
46 #include "configuration.h"
47 #include "utils.h"
49 using namespace tidl;
51 extern
52 bool RunNetwork(DeviceType           device_type,
53                 const DeviceIds&     ids,
54                 const Configuration& c,
55                 std::istream&        input,
56                 std::ostream&        output);
58 void* run_network(void *data);
60 struct ThreadArg
61 {
62     ThreadArg(const DeviceIds& device_ids, const std::string& s):
63         ids(device_ids), config_file(s) {}
65     DeviceIds   ids;
66     std::string config_file;
67 };
69 bool thread_status[2];
71 bool RunMultipleExecutors(const std::string& config_file_1,
72                           const std::string& config_file_2,
73                           uint32_t num_devices_available)
74 {
75     // If there is only 1 device available, skip
76     if (num_devices_available == 1)
77         return true;
79     DeviceIds ids1, ids2;
81     if (num_devices_available == 4)
82     {
83         ids1 = {DeviceId::ID2, DeviceId::ID3};
84         ids2 = {DeviceId::ID0, DeviceId::ID1};
85     }
86     else
87     {
88         ids1 = {DeviceId::ID0};
89         ids2 = {DeviceId::ID1};
90     }
92     // Set up devices and config files for each thread
93     ThreadArg arg1(ids2, config_file_1);
94     ThreadArg arg2(ids1, config_file_2);
96     // Run network 1 in a thread
97     std::cout << std::endl << "Multiple Executor..." << std::endl;
98     std::cout << "Running network "
99               << arg1.config_file.substr(arg1.config_file.find("tidl"))
100               << " on EVEs: ";
101     for (DeviceId id : arg1.ids)
102         std::cout << static_cast<int>(id) << " ";
103     std::cout << " in thread 0" << std::endl;
105     pthread_t network_thread_1;
106     pthread_create(&network_thread_1, 0, &run_network, &arg1);
108     // Run network 2 in a thread
109     std::cout << "Running network "
110               << arg2.config_file.substr(arg2.config_file.find("tidl"))
111               << " on EVEs: ";
112     for (DeviceId id : arg2.ids)
113         std::cout << static_cast<int>(id) << " ";
114     std::cout << " in thread 1" << std::endl;
116     pthread_t network_thread_2;
117     pthread_create(&network_thread_2, 0, &run_network, &arg2);
119     // Wait for both networks to complete
120     void *thread_return_val1;
121     void *thread_return_val2;
122     pthread_join(network_thread_1, &thread_return_val1);
123     pthread_join(network_thread_2, &thread_return_val2);
125     if (thread_return_val1 == 0 || thread_return_val2 == 0)
126     {
127         std::cout << "Multiple executors: FAILED" << std::endl;
128         return false;
129     }
131     std::cout << "Multiple executors: PASSED" << std::endl;
132     return true;
136 void* run_network(void *data)
138     const ThreadArg* arg = static_cast<const ThreadArg *>(data);
140     const DeviceIds& ids = arg->ids;
141     const std::string& config_file = arg->config_file;
143     // Read the TI DL configuration file
144     Configuration configuration;
145     bool status = configuration.ReadFromFile(config_file);
146     assert (status != false);
148     configuration.outData += std::to_string(pthread_self());
150     // Open input and output files
151     std::ifstream input_data_file(configuration.inData, std::ios::binary);
152     std::ofstream output_data_file(configuration.outData, std::ios::binary);
153     assert (input_data_file.good());
154     assert (output_data_file.good());
156     RunNetwork(DeviceType::EVE, ids, configuration,
157                input_data_file, output_data_file);
159     input_data_file.close();
160     output_data_file.close();
162     // Return 1 for true, 0 for false. void * pattern follows example from:
163     // "Advanced programming in the Unix Environment"
164     if (!status) return ((void *)0);
166     return ((void *)1);