• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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