| 100 | } |
| 101 | |
| 102 | MaceStatus Workspace::LoadModelTensor(const NetDef &net_def, Runtime *runtime, |
| 103 | const unsigned char *model_data, |
| 104 | const index_t model_data_size) { |
| 105 | // When model has no weight, return immediately. Otherwise, |
| 106 | // `MakeSliceBuffer` will try to map nullptr when running on GPU. |
| 107 | if (model_data == nullptr && model_data_size == 0) { |
| 108 | LOG(WARNING) << "Model has no weight, ignoring loading model tensor"; |
| 109 | return MaceStatus::MACE_SUCCESS; |
| 110 | } |
| 111 | MACE_CHECK(model_data != nullptr && model_data_size > 0); |
| 112 | MACE_LATENCY_LOGGER(1, "Load model tensors"); |
| 113 | index_t valid_data_size = NetDefHelper::GetModelValidSize(net_def); |
| 114 | VLOG(3) << "Model valid data size: " << valid_data_size; |
| 115 | if (model_data_size >= 0) { |
| 116 | MACE_CHECK(valid_data_size <= model_data_size, |
| 117 | valid_data_size, " should be smaller than ", model_data_size); |
| 118 | } |
| 119 | |
| 120 | const RuntimeType runtime_type = runtime->GetRuntimeType(); |
| 121 | auto slice_parent = runtime->MakeSliceBuffer(net_def, model_data, |
| 122 | valid_data_size); |
| 123 | diffused_buffer_ = (slice_parent == nullptr); |
| 124 | if (diffused_buffer_) { |
| 125 | bool is_quantize_model = NetDefHelper::IsQuantizedModel(net_def); |
| 126 | for (const auto &const_tensor : net_def.tensors()) { |
| 127 | MACE_LATENCY_LOGGER(2, "Load tensor ", const_tensor.name()); |
| 128 | VLOG(3) << "Tensor name: " << const_tensor.name() |
| 129 | << ", data type: " << const_tensor.data_type() << ", shape: " |
| 130 | << MakeString(std::vector<index_t>(const_tensor.dims().begin(), |
| 131 | const_tensor.dims().end())); |
| 132 | std::vector<index_t> dims; |
| 133 | for (const index_t d : const_tensor.dims()) { |
| 134 | dims.push_back(d); |
| 135 | } |
| 136 | |
| 137 | auto dst_data_type = |
| 138 | runtime->GetComputeDataType(net_def, const_tensor); |
| 139 | auto tensor = make_unique<Tensor>( |
| 140 | runtime, dst_data_type, dims, true, const_tensor.name()); |
| 141 | runtime->AllocateBufferForTensor(tensor.get(), BufRentType::RENT_PRIVATE); |
| 142 | |
| 143 | const index_t tensor_end = const_tensor.offset() + |
| 144 | tensor->size() * GetEnumTypeSize(const_tensor.data_type()); |
| 145 | MACE_CHECK(tensor_end <= model_data_size, "tensor_end (", tensor_end, |
| 146 | ") should <= ", model_data_size); |
| 147 | |
| 148 | if (runtime_type == RuntimeType::RT_CPU && |
| 149 | const_tensor.data_type() == DataType::DT_HALF) { |
| 150 | // uncompress the weights of fp16 |
| 151 | auto org_data = reinterpret_cast<const half *>( |
| 152 | model_data + const_tensor.offset()); |
| 153 | float *dst_data = tensor->mutable_data<float>(); |
| 154 | for (int i = 0; i < const_tensor.data_size(); ++i) { |
| 155 | dst_data[i] = half_float::half_cast<float>(org_data[i]); |
| 156 | } |
| 157 | } else if (!is_quantize_model && const_tensor.quantized()) { |
| 158 | // uncompress the weights of uint8 |
| 159 | if (dst_data_type != DT_FLOAT) { |
no test coverage detected