2 * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include "InputDataLoader.h"
19 #include <dio_hdf5/HDF5Importer.h>
20 #include <loco/IR/Graph.h>
21 #include <luci/IR/CircleNodes.h>
28 using DataType = loco::DataType;
29 using Shape = std::vector<loco::Dimension>;
31 namespace circle_eval_diff
34 // Check the type and the shape of CircleInput
35 void verifyTypeShape(const luci::CircleInput *input_node, const DataType &dtype, const Shape &shape)
38 if (dtype != input_node->dtype())
39 throw std::runtime_error("Wrong input type.");
41 if (shape.size() != input_node->rank())
42 throw std::runtime_error("Input rank mismatch.");
44 for (uint32_t i = 0; i < shape.size(); i++)
46 if (not(shape.at(i) == input_node->dim(i)))
47 throw std::runtime_error("Input shape mismatch.");
51 std::vector<size_t> getEachByteSizeOf(const std::vector<loco::Node *> &nodes)
53 std::vector<size_t> vec;
55 for (const auto node : nodes)
57 const auto input_node = loco::must_cast<const luci::CircleInput *>(node);
58 const auto dtype_size = loco::size(input_node->dtype());
59 size_t element_size = 1;
61 for (uint32_t index = 0; index < input_node->rank(); index++)
63 element_size *= input_node->dim(index).value();
66 vec.push_back(element_size * dtype_size);
72 size_t getTotalByteSizeOf(const std::vector<loco::Node *> &nodes)
74 size_t total_byte_size = 0;
76 for (const auto node : nodes)
78 const auto input_node = loco::must_cast<const luci::CircleInput *>(node);
79 size_t byte_size = loco::size(input_node->dtype());
81 for (uint32_t index = 0; index < input_node->rank(); index++)
83 byte_size *= input_node->dim(index).value();
86 total_byte_size += byte_size;
89 return total_byte_size;
92 } // namespace circle_eval_diff
94 namespace circle_eval_diff
97 HDF5Loader::HDF5Loader(const std::string &file_path, const std::vector<loco::Node *> &input_nodes)
98 : _input_nodes{input_nodes}
102 using HDF5Importer = dio::hdf5::HDF5Importer;
104 _hdf5 = std::make_unique<HDF5Importer>(file_path);
105 _hdf5->importGroup("value");
107 catch (const H5::Exception &e)
109 H5::Exception::printErrorStack();
110 throw std::runtime_error("HDF5 error occurred.");
114 uint32_t HDF5Loader::size(void) const { return _hdf5->numData(); }
116 InputDataLoader::Data HDF5Loader::get(uint32_t data_idx) const
119 data.resize(_input_nodes.size());
121 for (uint32_t input_idx = 0; input_idx < _input_nodes.size(); input_idx++)
123 auto input_node = loco::must_cast<luci::CircleInput *>(_input_nodes.at(input_idx));
124 assert(input_node->index() == input_idx);
126 data.at(input_idx) = *createEmptyTensor(input_node).get();
128 auto input_buffer = data.at(input_idx).buffer();
129 const auto input_buffer_bytes = data.at(input_idx).byte_size();
133 if (_hdf5->isRawData())
135 _hdf5->readTensor(data_idx, input_idx, input_buffer, input_buffer_bytes);
141 _hdf5->readTensor(data_idx, input_idx, &dtype, &shape, input_buffer, input_buffer_bytes);
143 // Check the type and the shape of the input data is valid
144 verifyTypeShape(input_node, dtype, shape);
147 catch (const H5::Exception &e)
149 H5::Exception::printErrorStack();
150 throw std::runtime_error("HDF5 error occurred.");
157 DirectoryLoader::DirectoryLoader(const std::string &dir_path,
158 const std::vector<loco::Node *> &input_nodes)
159 : _input_nodes{input_nodes}
161 DIR *dir = opendir(dir_path.c_str());
164 throw std::runtime_error("Cannot open directory \"" + dir_path + "\".");
167 struct dirent *entry = nullptr;
168 const auto input_total_bytes = getTotalByteSizeOf(input_nodes);
169 while ((entry = readdir(dir)))
171 // Skip if the entry is not a regular file
172 if (entry->d_type != DT_REG)
175 _data_paths.push_back(dir_path + "/" + entry->d_name);
181 uint32_t DirectoryLoader::size(void) const { return _data_paths.size(); }
183 InputDataLoader::Data DirectoryLoader::get(uint32_t data_idx) const
186 const auto input_total_bytes = getTotalByteSizeOf(_input_nodes);
187 std::vector<char> input_data(input_total_bytes);
188 const auto raw_data_path = _data_paths.at(data_idx);
189 std::ifstream fs(raw_data_path, std::ifstream::binary);
193 throw std::runtime_error("Cannot open file \"" + raw_data_path + "\".");
195 if (fs.read(input_data.data(), input_total_bytes).fail())
197 throw std::runtime_error("Failed to read raw data from file \"" + raw_data_path + "\".");
200 // Make Tensor from raw data
201 auto input_data_cur = input_data.data();
204 data.resize(_input_nodes.size());
205 std::vector<size_t> input_bytes = getEachByteSizeOf(_input_nodes);
206 for (uint32_t index = 0; index < _input_nodes.size(); index++)
208 const auto input_node = loco::must_cast<const luci::CircleInput *>(_input_nodes.at(index));
209 auto &tensor = data.at(index);
210 tensor = *createEmptyTensor(input_node).get();
211 auto buffer = tensor.buffer();
212 std::memcpy(buffer, input_data_cur, input_bytes.at(index));
213 input_data_cur += input_bytes.at(index);
219 std::unique_ptr<InputDataLoader> makeDataLoader(const std::string &file_path,
220 const InputFormat &format,
221 const std::vector<loco::Node *> &input_nodes)
225 case InputFormat::H5:
227 return std::make_unique<HDF5Loader>(file_path, input_nodes);
229 case InputFormat::DIR:
231 return std::make_unique<DirectoryLoader>(file_path, input_nodes);
234 throw std::runtime_error{"Unsupported input format."};
238 } // namespace circle_eval_diff