1 /**
2 * Copyright 2020 Huawei Technologies Co., Ltd
3 *
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
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
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.
15 */
16 #include "include/api/types.h"
17 #include <fstream>
18 #include <numeric>
19 #include "securec/include/securec.h"
20 #include "mindspore/core/ir/api_tensor_impl.h"
21 #include "mindspore/core/utils/convert_utils_base.h"
22 #include "utils/file_utils.h"
23
24 namespace mindspore {
25 class Buffer::Impl {
26 public:
Impl()27 Impl() : data_() {}
28 ~Impl() = default;
Impl(const void * data,size_t data_len)29 Impl(const void *data, size_t data_len) {
30 if (data != nullptr) {
31 (void)SetData(data, data_len);
32 } else {
33 ResizeData(data_len);
34 }
35 }
36
Data() const37 const void *Data() const { return data_.data(); }
MutableData()38 void *MutableData() { return data_.data(); }
DataSize() const39 size_t DataSize() const { return data_.size(); }
40
ResizeData(size_t data_len)41 bool ResizeData(size_t data_len) {
42 data_.resize(data_len);
43 return true;
44 }
45
SetData(const void * data,size_t data_len)46 bool SetData(const void *data, size_t data_len) {
47 ResizeData(data_len);
48 if (DataSize() != data_len) {
49 MS_LOG(ERROR) << "Set data failed, tensor current data size " << DataSize() << " not match data len " << data_len;
50 return false;
51 }
52
53 if (data == nullptr) {
54 return data_len == 0;
55 }
56
57 if (MutableData() == nullptr) {
58 MS_LOG(ERROR) << "Set data failed, data len " << data_len;
59 return false;
60 }
61
62 auto ret = memcpy_s(MutableData(), DataSize(), data, data_len);
63 if (ret != 0) {
64 MS_LOG(ERROR) << "Set data memcpy_s failed, ret = " << ret;
65 return false;
66 }
67 return true;
68 }
69
70 protected:
71 std::vector<uint8_t> data_;
72 };
73
74 class TensorDefaultImpl : public MSTensor::Impl {
75 public:
TensorDefaultImpl()76 TensorDefaultImpl() : buffer_(), name_(), type_(DataType::kTypeUnknown), shape_() {}
77 ~TensorDefaultImpl() override = default;
TensorDefaultImpl(const std::string & name,enum DataType type,const std::vector<int64_t> & shape,const void * data,size_t data_len)78 TensorDefaultImpl(const std::string &name, enum DataType type, const std::vector<int64_t> &shape, const void *data,
79 size_t data_len)
80 : buffer_(data, data_len), name_(name), type_(type), shape_(shape) {}
81
Name() const82 const std::string &Name() const override { return name_; }
DataType() const83 enum DataType DataType() const override { return type_; }
Shape() const84 const std::vector<int64_t> &Shape() const override { return shape_; }
85
Data() const86 std::shared_ptr<const void> Data() const override {
87 return std::shared_ptr<const void>(buffer_.Data(), [](const void *) {});
88 }
89
MutableData()90 void *MutableData() override { return buffer_.MutableData(); }
DataSize() const91 size_t DataSize() const override { return buffer_.DataSize(); }
92
IsDevice() const93 bool IsDevice() const override { return false; }
94
Clone() const95 std::shared_ptr<Impl> Clone() const override {
96 return std::make_shared<TensorDefaultImpl>(name_, type_, shape_, buffer_.Data(), buffer_.DataSize());
97 }
98
99 private:
100 Buffer buffer_;
101 std::string name_;
102 enum DataType type_;
103 std::vector<int64_t> shape_;
104 };
105
106 class TensorReferenceImpl : public MSTensor::Impl {
107 public:
TensorReferenceImpl()108 TensorReferenceImpl()
109 : data_(nullptr), data_size_(0), name_(), type_(DataType::kTypeUnknown), shape_(), is_device_(false) {}
110 ~TensorReferenceImpl() override = default;
TensorReferenceImpl(const std::string & name,enum DataType type,const std::vector<int64_t> & shape,const void * data,size_t data_len,bool is_device)111 TensorReferenceImpl(const std::string &name, enum DataType type, const std::vector<int64_t> &shape, const void *data,
112 size_t data_len, bool is_device)
113 : data_(data), data_size_(data_len), name_(name), type_(type), shape_(shape), is_device_(is_device) {}
114
Name() const115 const std::string &Name() const override { return name_; }
DataType() const116 enum DataType DataType() const override { return type_; }
Shape() const117 const std::vector<int64_t> &Shape() const override { return shape_; }
118
Data() const119 std::shared_ptr<const void> Data() const override {
120 return std::shared_ptr<const void>(data_, [](const void *) {});
121 }
122
MutableData()123 void *MutableData() override { return const_cast<void *>(data_); }
DataSize() const124 size_t DataSize() const override { return data_size_; }
125
IsDevice() const126 bool IsDevice() const override { return is_device_; }
127
Clone() const128 std::shared_ptr<Impl> Clone() const override {
129 return std::make_shared<TensorReferenceImpl>(name_, type_, shape_, data_, data_size_, is_device_);
130 }
131
132 protected:
133 const void *data_;
134 size_t data_size_;
135 std::string name_;
136 enum DataType type_;
137 std::vector<int64_t> shape_;
138 bool is_device_;
139 };
140
CreateTensor(const std::vector<char> & name,enum DataType type,const std::vector<int64_t> & shape,const void * data,size_t data_len)141 MSTensor *MSTensor::CreateTensor(const std::vector<char> &name, enum DataType type, const std::vector<int64_t> &shape,
142 const void *data, size_t data_len) noexcept {
143 std::string name_str = CharToString(name);
144 try {
145 std::shared_ptr<Impl> impl = std::make_shared<TensorDefaultImpl>(name_str, type, shape, data, data_len);
146 MSTensor *ret = new MSTensor(impl);
147 return ret;
148 } catch (const std::bad_alloc &) {
149 MS_LOG(ERROR) << "Malloc memory failed.";
150 return nullptr;
151 } catch (...) {
152 MS_LOG(ERROR) << "Unknown error occurred.";
153 return nullptr;
154 }
155 }
156
CreateRefTensor(const std::vector<char> & name,enum DataType type,const std::vector<int64_t> & shape,const void * data,size_t data_len)157 MSTensor *MSTensor::CreateRefTensor(const std::vector<char> &name, enum DataType type,
158 const std::vector<int64_t> &shape, const void *data, size_t data_len) noexcept {
159 std::string name_str = CharToString(name);
160 try {
161 std::shared_ptr<Impl> impl = std::make_shared<TensorReferenceImpl>(name_str, type, shape, data, data_len, false);
162 MSTensor *ret = new MSTensor(impl);
163 return ret;
164 } catch (const std::bad_alloc &) {
165 MS_LOG(ERROR) << "Malloc memory failed.";
166 return nullptr;
167 } catch (...) {
168 MS_LOG(ERROR) << "Unknown error occurred.";
169 return nullptr;
170 }
171 }
172
CreateDevTensor(const std::vector<char> & name,enum DataType type,const std::vector<int64_t> & shape,const void * data,size_t data_len)173 MSTensor *MSTensor::CreateDevTensor(const std::vector<char> &name, enum DataType type,
174 const std::vector<int64_t> &shape, const void *data, size_t data_len) noexcept {
175 std::string name_str = CharToString(name);
176 try {
177 std::shared_ptr<Impl> impl = std::make_shared<TensorReferenceImpl>(name_str, type, shape, data, data_len, true);
178 MSTensor *ret = new MSTensor(impl);
179 return ret;
180 } catch (const std::bad_alloc &) {
181 MS_LOG(ERROR) << "Malloc memory failed.";
182 return nullptr;
183 } catch (...) {
184 MS_LOG(ERROR) << "Unknown error occurred.";
185 return nullptr;
186 }
187 }
188
CreateImageTensor(const std::vector<char> & image_file)189 MSTensor *MSTensor::CreateImageTensor(const std::vector<char> &image_file) noexcept {
190 std::string image_file_str = CharToString(image_file);
191
192 try {
193 auto realpath = FileUtils::GetRealPath(image_file_str.c_str());
194 if (!realpath.has_value()) {
195 MS_LOG(ERROR) << "Get real path failed, path=" << image_file_str;
196 return nullptr;
197 }
198
199 // Read image file
200 auto file = realpath.value();
201 if (file.empty()) {
202 MS_LOG(ERROR) << "can not find any input file.";
203 return nullptr;
204 }
205
206 std::ifstream ifs(file, std::ios::in | std::ios::binary);
207 if (!ifs.good()) {
208 MS_LOG(ERROR) << "File: " + file + " does not exist.";
209 return nullptr;
210 }
211 if (!ifs.is_open()) {
212 MS_LOG(ERROR) << "File: " + file + " open failed.";
213 return nullptr;
214 }
215
216 auto &io_seekg1 = ifs.seekg(0, std::ios::end);
217 if (!io_seekg1.good() || io_seekg1.fail() || io_seekg1.bad()) {
218 ifs.close();
219 MS_LOG(ERROR) << "Failed to seekg file: " + file;
220 return nullptr;
221 }
222
223 size_t size = static_cast<size_t>(ifs.tellg());
224 MSTensor *ret =
225 new MSTensor(file, mindspore::DataType::kNumberTypeUInt8, {static_cast<int64_t>(size)}, nullptr, size);
226
227 auto &io_seekg2 = ifs.seekg(0, std::ios::beg);
228 if (!io_seekg2.good() || io_seekg2.fail() || io_seekg2.bad()) {
229 ifs.close();
230 MS_LOG(ERROR) << "Failed to seekg file: " + file;
231 return nullptr;
232 }
233
234 auto &io_read = ifs.read(reinterpret_cast<char *>(ret->MutableData()), static_cast<std::streamsize>(size));
235 if (!io_read.good() || io_read.fail() || io_read.bad()) {
236 ifs.close();
237 MS_LOG(ERROR) << "Failed to read file: " + file;
238 return nullptr;
239 }
240 ifs.close();
241
242 return ret;
243 } catch (const std::bad_alloc &) {
244 MS_LOG(ERROR) << "Malloc memory failed.";
245 return nullptr;
246 } catch (...) {
247 MS_LOG(ERROR) << "Unknown error occurred.";
248 return nullptr;
249 }
250 }
251
CharStringsToTensor(const std::vector<char> & name,const std::vector<std::vector<char>> & str)252 MSTensor *MSTensor::CharStringsToTensor(const std::vector<char> &name, const std::vector<std::vector<char>> &str) {
253 // num(4 bytes) + offset1(4 bytes) + offset2(4 bytes) + ... + data1(str1.len) + data2(str2.len) + ...
254 // str1.len() = offset2 - offset1
255 // data1.begin() = start + offset1
256 size_t mem_size = 0;
257 mem_size += sizeof(int32_t); // for num
258 for (const auto &s : str) {
259 mem_size += sizeof(int32_t); // for offset
260 mem_size += s.size(); // for data
261 }
262
263 auto tensor = CreateTensor(name, DataType::kObjectTypeString, {static_cast<int64_t>(mem_size)}, nullptr, mem_size);
264 if (tensor == nullptr) {
265 MS_LOG(ERROR) << "Create tensor failed.";
266 return nullptr;
267 }
268
269 int32_t *data = reinterpret_cast<int32_t *>(tensor->MutableData());
270 if (data == nullptr) {
271 MS_LOG(ERROR) << "Create tensor failed.";
272 DestroyTensorPtr(tensor);
273 return nullptr;
274 }
275 uint8_t *cur_data = reinterpret_cast<uint8_t *>(data + 1 + str.size());
276 *reinterpret_cast<int32_t *>(data) = str.size();
277 for (size_t i = 0; i < str.size(); ++i) {
278 int32_t offset = (cur_data - reinterpret_cast<uint8_t *>(data));
279 data[i + 1] = offset;
280 if (str[i].empty()) {
281 continue;
282 }
283 auto ret = memcpy_s(reinterpret_cast<void *>(cur_data), str[i].size(), str[i].data(), str[i].size());
284 if (ret != 0) {
285 MS_LOG(ERROR) << "memcpy_s failed, ret = " << ret;
286 DestroyTensorPtr(tensor);
287 return nullptr;
288 }
289 cur_data += str[i].size();
290 }
291
292 return tensor;
293 }
294
TensorToStringChars(const MSTensor & tensor)295 std::vector<std::vector<char>> MSTensor::TensorToStringChars(const MSTensor &tensor) {
296 if (tensor == nullptr || tensor.DataType() != DataType::kObjectTypeString || tensor.DataSize() < 4) {
297 MS_LOG(ERROR) << "Invalid tensor.";
298 return {};
299 }
300
301 std::vector<std::vector<char>> strings;
302 auto host_data = tensor.Data();
303 const int32_t *data = reinterpret_cast<const int32_t *>(host_data.get());
304 int32_t str_num = data[0];
305 if (str_num == 0) {
306 return {};
307 }
308 if (str_num < 0) {
309 MS_LOG(ERROR) << "str num " << str_num << " cannot be negative.";
310 return {};
311 }
312
313 if (tensor.DataSize() < (str_num + 1) * sizeof(int32_t)) {
314 MS_LOG(ERROR) << "Invalid tensor data size " << tensor.DataSize() << ", need "
315 << IntToSize(str_num + 1) * sizeof(int32_t) << " at least for " << str_num << " strings.";
316 return {};
317 }
318 for (size_t i = 0; i < static_cast<size_t>(str_num); ++i) {
319 strings.push_back({});
320 auto &str = strings[i];
321 int32_t str_len;
322 int32_t offset = data[i + 1];
323 if (i + 1 != static_cast<size_t>(str_num)) {
324 str_len = data[i + 1 + 1] - offset;
325 } else {
326 str_len = tensor.DataSize() - offset;
327 }
328
329 if (str_len == 0) {
330 continue;
331 }
332
333 if (str_len < 0) {
334 MS_LOG(ERROR) << "str " << i << " len " << str_len << " cannot be negative.";
335 return {};
336 }
337
338 str.resize(str_len);
339 const uint8_t *cur_data = reinterpret_cast<const uint8_t *>(data) + offset;
340 auto ret = memcpy_s(reinterpret_cast<void *>(str.data()), str.size(), cur_data, str_len);
341 if (ret != 0) {
342 MS_LOG(ERROR) << "memcpy_s failed, ret = " << ret;
343 return {};
344 }
345 }
346
347 return strings;
348 }
349
DestroyTensorPtr(MSTensor * tensor)350 void MSTensor::DestroyTensorPtr(MSTensor *tensor) noexcept {
351 if (tensor != nullptr) {
352 delete tensor;
353 }
354 }
355
MSTensor()356 MSTensor::MSTensor() : impl_(std::make_shared<TensorDefaultImpl>()) {}
MSTensor(std::nullptr_t)357 MSTensor::MSTensor(std::nullptr_t) : impl_(nullptr) {}
MSTensor(const std::shared_ptr<Impl> & impl)358 MSTensor::MSTensor(const std::shared_ptr<Impl> &impl) : impl_(impl) { MS_EXCEPTION_IF_NULL(impl); }
MSTensor(const std::vector<char> & name,enum DataType type,const std::vector<int64_t> & shape,const void * data,size_t data_len)359 MSTensor::MSTensor(const std::vector<char> &name, enum DataType type, const std::vector<int64_t> &shape,
360 const void *data, size_t data_len)
361 : impl_(std::make_shared<TensorDefaultImpl>(CharToString(name), type, shape, data, data_len)) {}
362 MSTensor::~MSTensor() = default;
363
operator ==(std::nullptr_t) const364 bool MSTensor::operator==(std::nullptr_t) const { return impl_ == nullptr; }
365
operator !=(std::nullptr_t) const366 bool MSTensor::operator!=(std::nullptr_t) const { return impl_ != nullptr; }
367
Clone() const368 MSTensor *MSTensor::Clone() const {
369 MS_EXCEPTION_IF_NULL(impl_);
370 try {
371 MSTensor *ret = new MSTensor();
372 ret->impl_ = impl_->Clone();
373 return ret;
374 } catch (const std::bad_alloc &) {
375 MS_LOG(ERROR) << "Malloc memory failed.";
376 return nullptr;
377 } catch (...) {
378 MS_LOG(ERROR) << "Unknown error occurred.";
379 return nullptr;
380 }
381 }
382
CharName() const383 std::vector<char> MSTensor::CharName() const {
384 MS_EXCEPTION_IF_NULL(impl_);
385 return StringToChar(impl_->Name());
386 }
387
DataType() const388 enum DataType MSTensor::DataType() const {
389 MS_EXCEPTION_IF_NULL(impl_);
390 return impl_->DataType();
391 }
392
Shape() const393 const std::vector<int64_t> &MSTensor::Shape() const {
394 MS_EXCEPTION_IF_NULL(impl_);
395 return impl_->Shape();
396 }
397
ElementNum() const398 int64_t MSTensor::ElementNum() const {
399 MS_EXCEPTION_IF_NULL(impl_);
400 const auto &shape = impl_->Shape();
401 if (shape.empty()) {
402 // element number of scalar is 1
403 return 1;
404 }
405 return std::accumulate(shape.begin(), shape.end(), 1, std::multiplies<int64_t>());
406 }
407
Data() const408 std::shared_ptr<const void> MSTensor::Data() const {
409 MS_EXCEPTION_IF_NULL(impl_);
410 return impl_->Data();
411 }
412
MutableData()413 void *MSTensor::MutableData() {
414 MS_EXCEPTION_IF_NULL(impl_);
415 return impl_->MutableData();
416 }
417
DataSize() const418 size_t MSTensor::DataSize() const {
419 MS_EXCEPTION_IF_NULL(impl_);
420 return impl_->DataSize();
421 }
422
IsDevice() const423 bool MSTensor::IsDevice() const {
424 MS_EXCEPTION_IF_NULL(impl_);
425 return impl_->IsDevice();
426 }
427
SetShape(const std::vector<int64_t> &)428 void MSTensor::SetShape(const std::vector<int64_t> &) { MS_LOG_EXCEPTION << "Invalid implement."; }
429
SetDataType(enum DataType)430 void MSTensor::SetDataType(enum DataType) { MS_LOG_EXCEPTION << "Invalid implement."; }
431
SetTensorName(const std::string &)432 void MSTensor::SetTensorName(const std::string &) { MS_LOG_EXCEPTION << "Invalid implement."; }
433
SetAllocator(std::shared_ptr<Allocator>)434 void MSTensor::SetAllocator(std::shared_ptr<Allocator>) { MS_LOG_EXCEPTION << "Invalid implement."; }
435
allocator() const436 std::shared_ptr<Allocator> MSTensor::allocator() const { MS_LOG_EXCEPTION << "Invalid implement."; }
437
SetFormat(mindspore::Format)438 void MSTensor::SetFormat(mindspore::Format) { MS_LOG_EXCEPTION << "Invalid implement."; }
439
format() const440 mindspore::Format MSTensor::format() const { MS_LOG_EXCEPTION << "Invalid implement."; }
441
SetData(void *)442 void MSTensor::SetData(void *) { MS_LOG_EXCEPTION << "Invalid implement."; }
443
QuantParams() const444 std::vector<QuantParam> MSTensor::QuantParams() const { MS_LOG_EXCEPTION << "Invalid implement."; }
445
SetQuantParams(std::vector<QuantParam>)446 void MSTensor::SetQuantParams(std::vector<QuantParam>) { MS_LOG_EXCEPTION << "Invalid implement."; }
447
Buffer()448 Buffer::Buffer() : impl_(std::make_shared<Impl>()) {}
Buffer(const void * data,size_t data_len)449 Buffer::Buffer(const void *data, size_t data_len) : impl_(std::make_shared<Impl>(data, data_len)) {}
450 Buffer::~Buffer() = default;
451
Clone() const452 Buffer Buffer::Clone() const {
453 MS_EXCEPTION_IF_NULL(impl_);
454 Buffer ret;
455 ret.impl_ = std::make_shared<Impl>(*impl_);
456 return ret;
457 }
458
Data() const459 const void *Buffer::Data() const {
460 MS_EXCEPTION_IF_NULL(impl_);
461 return impl_->Data();
462 }
463
MutableData()464 void *Buffer::MutableData() {
465 MS_EXCEPTION_IF_NULL(impl_);
466 return impl_->MutableData();
467 }
468
DataSize() const469 size_t Buffer::DataSize() const {
470 MS_EXCEPTION_IF_NULL(impl_);
471 return impl_->DataSize();
472 }
473
ResizeData(size_t data_len)474 bool Buffer::ResizeData(size_t data_len) {
475 MS_EXCEPTION_IF_NULL(impl_);
476 return impl_->ResizeData(data_len);
477 }
478
SetData(const void * data,size_t data_len)479 bool Buffer::SetData(const void *data, size_t data_len) {
480 MS_EXCEPTION_IF_NULL(impl_);
481 return impl_->SetData(data, data_len);
482 }
483
CharVersion()484 std::vector<char> CharVersion() { return {}; }
485 } // namespace mindspore
486