• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 2017 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/compiler/tf2xla/xla_compilation_device.h"
17 
18 #include <functional>
19 #include <memory>
20 
21 #include "tensorflow/compiler/tf2xla/shape_util.h"
22 #include "tensorflow/compiler/tf2xla/sharding_util.h"
23 #include "tensorflow/compiler/tf2xla/xla_context.h"
24 #include "tensorflow/compiler/tf2xla/xla_helpers.h"
25 #include "tensorflow/compiler/xla/client/xla_builder.h"
26 #include "tensorflow/core/common_runtime/local_device.h"
27 #include "tensorflow/core/framework/device_base.h"
28 #include "tensorflow/core/platform/mem.h"
29 
30 namespace tensorflow {
31 
32 // The XlaCompilationAllocator doesn't actually back any Tensors with storage
33 // buffers of values: instead for each Tensor it stores a
34 // XlaExpression which corresponds to the XLA computation
35 // represented by the Tensor.
36 class XlaCompilationAllocator : public Allocator {
37  public:
XlaCompilationAllocator()38   XlaCompilationAllocator() {}
~XlaCompilationAllocator()39   ~XlaCompilationAllocator() override {}
40 
Name()41   string Name() override { return "xla_compilation"; }
42 
AllocateRaw(size_t alignment,size_t num_bytes)43   void* AllocateRaw(size_t alignment, size_t num_bytes) override {
44     // Regardless of the size requested, always allocates an XlaExpression.
45     // Respects the alignment request because there is alignment checking even
46     // for Tensors whose data is never accessed.
47     void* p = port::AlignedMalloc(sizeof(XlaExpression), alignment);
48     XlaExpression* expression = reinterpret_cast<XlaExpression*>(p);
49     new (expression) XlaExpression();
50     return expression;
51   }
52 
DeallocateRaw(void * ptr)53   void DeallocateRaw(void* ptr) override {
54     XlaExpression* expression = reinterpret_cast<XlaExpression*>(ptr);
55     expression->~XlaExpression();
56     port::AlignedFree(ptr);
57   }
58 
59   // Make sure that even tensors with 0 elements have allocated
60   // buffers, so they get ids to track.
ShouldAllocateEmptyTensors()61   bool ShouldAllocateEmptyTensors() override { return true; }
62 
63  private:
64   // Don't run any constructors or destructors for complex objects,
65   // since there is no backing store for the tensor to run them
66   // on. strings are the only complex objects currently stored in
67   // Tensors. If others are added, this set of overrides must be
68   // extended to include them.
RunStringCtor(string * p,size_t n)69   void RunStringCtor(string* p, size_t n) override {}
RunStringDtor(string * p,size_t n)70   void RunStringDtor(string* p, size_t n) override {}
RunResourceCtor(ResourceHandle * p,size_t n)71   void RunResourceCtor(ResourceHandle* p, size_t n) override {}
RunResourceDtor(ResourceHandle * p,size_t n)72   void RunResourceDtor(ResourceHandle* p, size_t n) override {}
73 };
74 
XlaCompilationDevice(const SessionOptions & options,DeviceType type)75 XlaCompilationDevice::XlaCompilationDevice(const SessionOptions& options,
76                                            DeviceType type)
77     : LocalDevice(options, Device::BuildDeviceAttributes(
78                                absl::StrCat("/device:", type.type(), ":0"),
79                                type, Bytes(256 << 20), DeviceLocality(),
80                                absl::StrCat("device: XLA compilation device ",
81                                             type.type()))),
82       allocator_(new XlaCompilationAllocator()) {}
83 
~XlaCompilationDevice()84 XlaCompilationDevice::~XlaCompilationDevice() {}
85 
GetAllocator(AllocatorAttributes attr)86 Allocator* XlaCompilationDevice::GetAllocator(AllocatorAttributes attr) {
87   return allocator_.get();
88 }
89 
Compute(OpKernel * op_kernel,OpKernelContext * context)90 void XlaCompilationDevice::Compute(OpKernel* op_kernel,
91                                    OpKernelContext* context) {
92   VLOG(4) << "XlaCompilationDevice::Compute "
93           << FormatNodeDefForError(op_kernel->def());
94   auto* b = XlaContext::Get(context).builder();
95   xla::OpMetadata metadata;
96   metadata.set_op_type(op_kernel->type_string());
97   metadata.set_op_name(op_kernel->name());
98   b->SetOpMetadata(metadata);
99 
100   auto sharding_parse_result = ParseShardingFromDevice(
101       op_kernel->def(), std::numeric_limits<int>::max());
102   OP_REQUIRES_OK(context, sharding_parse_result.status());
103   absl::optional<xla::OpSharding> op_sharding =
104       sharding_parse_result.ValueOrDie();
105 
106   // If no sharding metadata is found, XLA is free to use whatever device it
107   // wants. In practice this usually has the effect of placing things on device
108   // 0.
109   xla::XlaScopedShardingAssignment assign_sharding(b, op_sharding);
110   op_kernel->Compute(context);
111 
112   b->ClearOpMetadata();
113   VLOG(4) << "Done";
114 }
115 
Sync()116 Status XlaCompilationDevice::Sync() { return Status::OK(); }
117 
MakeTensorFromProto(const TensorProto & tensor_proto,const AllocatorAttributes alloc_attrs,Tensor * tensor)118 Status XlaCompilationDevice::MakeTensorFromProto(
119     const TensorProto& tensor_proto, const AllocatorAttributes alloc_attrs,
120     Tensor* tensor) {
121   return errors::InvalidArgument(
122       "XLACompilationDevice::MakeTensorFromProto should not be called");
123 }
124 
125 }  // namespace tensorflow
126