xref: /aosp_15_r20/external/tensorflow/tensorflow/core/framework/resource_handle.cc (revision b6fb3261f9314811a0f4371741dbb8839866f948)
1 /* Copyright 2015 The TensorFlow Authors. All Rights Reserved.
2 
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6 
7     http://www.apache.org/licenses/LICENSE-2.0
8 
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ==============================================================================*/
15 
16 #include "tensorflow/core/framework/resource_handle.h"
17 
18 #include <string>
19 #include <utility>
20 #include <vector>
21 
22 #include "absl/strings/str_format.h"
23 #include "tensorflow/core/framework/resource_handle.pb.h"
24 #include "tensorflow/core/framework/tensor_shape.h"
25 #include "tensorflow/core/lib/core/errors.h"
26 #include "tensorflow/core/lib/strings/strcat.h"
27 #include "tensorflow/core/platform/demangle.h"
28 #include "tensorflow/core/platform/errors.h"
29 #include "tensorflow/core/platform/macros.h"
30 
31 namespace tensorflow {
32 
33 namespace {
DtypeAndShapesToString(const std::vector<DtypeAndPartialTensorShape> & dtype_and_shapes)34 std::string DtypeAndShapesToString(
35     const std::vector<DtypeAndPartialTensorShape>& dtype_and_shapes) {
36   std::vector<std::string> dtype_and_shape_strings;
37   dtype_and_shape_strings.reserve(dtype_and_shapes.size());
38   for (const DtypeAndPartialTensorShape& dtype_and_shape : dtype_and_shapes) {
39     // Note that it is a bit unfortunate to return int/enum as dtype, given we
40     // can't directly use DataTypeString due to circular dependency.
41     dtype_and_shape_strings.push_back(
42         absl::StrFormat("DType enum: %d, Shape: %s", dtype_and_shape.dtype,
43                         dtype_and_shape.shape.DebugString()));
44   }
45   return absl::StrFormat("[ %s ]", absl::StrJoin(dtype_and_shape_strings, ","));
46 }
47 }  // namespace
48 
49 // Must be declared here for pre-C++17 compatibility.
50 /* static */ constexpr const char* ResourceHandle::ANONYMOUS_NAME;
51 
ResourceHandle()52 ResourceHandle::ResourceHandle() {}
53 
ResourceHandle(const ResourceHandleProto & proto)54 ResourceHandle::ResourceHandle(const ResourceHandleProto& proto) {
55   TF_CHECK_OK(FromProto(proto));
56 }
57 
BuildResourceHandle(const ResourceHandleProto & proto,ResourceHandle * out)58 Status ResourceHandle::BuildResourceHandle(const ResourceHandleProto& proto,
59                                            ResourceHandle* out) {
60   if (out == nullptr)
61     return errors::Internal(
62         "BuildResourceHandle() was called with nullptr for the output");
63   return out->FromProto(proto);
64 }
65 
~ResourceHandle()66 ResourceHandle::~ResourceHandle() {}
67 
AsProto(ResourceHandleProto * proto) const68 void ResourceHandle::AsProto(ResourceHandleProto* proto) const {
69   proto->set_device(device());
70   proto->set_container(container());
71   proto->set_name(name());
72   proto->set_hash_code(hash_code());
73   proto->set_maybe_type_name(maybe_type_name());
74   for (const auto& dtype_and_shape_pair : dtypes_and_shapes_) {
75     auto dtype_and_shape = proto->add_dtypes_and_shapes();
76     dtype_and_shape->set_dtype(dtype_and_shape_pair.dtype);
77     dtype_and_shape_pair.shape.AsProto(dtype_and_shape->mutable_shape());
78   }
79 }
80 
FromProto(const ResourceHandleProto & proto)81 Status ResourceHandle::FromProto(const ResourceHandleProto& proto) {
82   set_device(proto.device());
83   set_container(proto.container());
84   set_name(proto.name());
85   set_hash_code(proto.hash_code());
86   set_maybe_type_name(proto.maybe_type_name());
87   std::vector<DtypeAndPartialTensorShape> dtypes_and_shapes;
88   for (const auto& dtype_and_shape : proto.dtypes_and_shapes()) {
89     DataType dtype = dtype_and_shape.dtype();
90     PartialTensorShape shape;
91     Status s = PartialTensorShape::BuildPartialTensorShape(
92         dtype_and_shape.shape(), &shape);
93     if (!s.ok()) {
94       return s;
95     }
96     dtypes_and_shapes.push_back(DtypeAndPartialTensorShape{dtype, shape});
97   }
98   dtypes_and_shapes_ = std::move(dtypes_and_shapes);
99   return OkStatus();
100 }
101 
SerializeAsString() const102 string ResourceHandle::SerializeAsString() const {
103   ResourceHandleProto proto;
104   AsProto(&proto);
105   return proto.SerializeAsString();
106 }
107 
ParseFromString(const string & s)108 bool ResourceHandle::ParseFromString(const string& s) {
109   ResourceHandleProto proto;
110   return proto.ParseFromString(s) && FromProto(proto).ok();
111 }
112 
DebugString() const113 string ResourceHandle::DebugString() const {
114   return absl::StrFormat(
115       "device: %s container: %s name: %s hash_code: 0x%X maybe_type_name %s, "
116       "dtype and shapes : %s",
117       device(), container(), name(), hash_code(),
118       port::Demangle(maybe_type_name()),
119       DtypeAndShapesToString(dtypes_and_shapes()));
120 }
SummarizeValue() const121 string ResourceHandle::SummarizeValue() const {
122   return absl::StrFormat(
123       "ResourceHandle(name=\"%s\", device=\"%s\", container=\"%s\", "
124       "type=\"%s\", dtype and shapes : \"%s\")",
125       name(), device(), container(), port::Demangle(maybe_type_name()),
126       DtypeAndShapesToString(dtypes_and_shapes()));
127 }
128 
MakeRefCountingHandle(ResourceBase * resource,const string & device_name,const TypeIndex & type_index,const std::vector<DtypeAndPartialTensorShape> & dtypes_and_shapes,const absl::optional<ManagedStackTrace> & definition_stack_trace)129 ResourceHandle ResourceHandle::MakeRefCountingHandle(
130     ResourceBase* resource, const string& device_name,
131     const TypeIndex& type_index,
132     const std::vector<DtypeAndPartialTensorShape>& dtypes_and_shapes,
133     const absl::optional<ManagedStackTrace>& definition_stack_trace) {
134   ResourceHandle result;
135   result.resource_.reset(resource, /*add_ref=*/false);
136   result.set_device(device_name);
137   // All resources owned by anonymous handles are put into the same container,
138   // and they get process-unique handle names.
139   result.set_container("Anonymous");
140   result.set_definition_stack_trace(definition_stack_trace);
141   result.set_name(
142       absl::StrFormat("Resource-%d-at-%p", GenerateUniqueId(), resource));
143   result.set_hash_code(type_index.hash_code());
144   result.set_maybe_type_name(type_index.name());
145   result.set_dtypes_and_shapes(dtypes_and_shapes);
146   return result;
147 }
148 
ValidateType(const TypeIndex & type_index) const149 Status ResourceHandle::ValidateType(const TypeIndex& type_index) const {
150   if (type_index.hash_code() != hash_code()) {
151     return errors::InvalidArgument(
152         "Trying to access a handle's resource using the wrong type. ",
153         "The handle points to a resource (name '", name(), "') of type '",
154         port::Demangle(maybe_type_name()), "' (hash code ", hash_code(),
155         ") but you are trying to access the resource as type '",
156         port::Demangle(type_index.name()), "' (hash code ",
157         type_index.hash_code(), ")");
158   }
159   return OkStatus();
160 }
161 
162 std::atomic<int64_t> ResourceHandle::current_id_;
163 
GenerateUniqueId()164 int64_t ResourceHandle::GenerateUniqueId() { return current_id_.fetch_add(1); }
165 
ProtoDebugString(const ResourceHandle & handle)166 string ProtoDebugString(const ResourceHandle& handle) {
167   return handle.DebugString();
168 }
169 
EncodeResourceHandleList(const ResourceHandle * p,int64_t n,std::unique_ptr<port::StringListEncoder> e)170 void EncodeResourceHandleList(const ResourceHandle* p, int64_t n,
171                               std::unique_ptr<port::StringListEncoder> e) {
172   ResourceHandleProto proto;
173   for (int i = 0; i < n; ++i) {
174     p[i].AsProto(&proto);
175     e->Append(proto);
176   }
177   e->Finalize();
178 }
179 
DecodeResourceHandleList(std::unique_ptr<port::StringListDecoder> d,ResourceHandle * ps,int64_t n)180 bool DecodeResourceHandleList(std::unique_ptr<port::StringListDecoder> d,
181                               ResourceHandle* ps, int64_t n) {
182   std::vector<uint32> sizes(n);
183   if (!d->ReadSizes(&sizes)) return false;
184 
185   ResourceHandleProto proto;
186   for (int i = 0; i < n; ++i) {
187     if (!proto.ParseFromArray(d->Data(sizes[i]), sizes[i])) {
188       return false;
189     }
190     if (!ps[i].FromProto(proto).ok()) {
191       return false;
192     }
193   }
194   return true;
195 }
196 
197 }  // namespace tensorflow
198