• 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 // Utility functions related to layouts of Shapes.
17 
18 #ifndef TENSORFLOW_COMPILER_XLA_LAYOUT_UTIL_H_
19 #define TENSORFLOW_COMPILER_XLA_LAYOUT_UTIL_H_
20 
21 #include <string>
22 
23 #include "absl/types/span.h"
24 #include "tensorflow/compiler/xla/layout.h"
25 #include "tensorflow/compiler/xla/shape.h"
26 #include "tensorflow/compiler/xla/status.h"
27 #include "tensorflow/compiler/xla/types.h"
28 #include "tensorflow/compiler/xla/xla_data.pb.h"
29 #include "tensorflow/core/platform/macros.h"
30 #include "tensorflow/core/platform/types.h"
31 
32 namespace xla {
33 
34 // Namespaced collection of (static) Layout utilities.
35 class LayoutUtil {
36  public:
37   // Creates a layout with the given minor-to-major dimension order. (This is a
38   // convenience function for protobuf construction.)
39   static Layout MakeLayout(absl::Span<const int64> minor_to_major,
40                            absl::Span<const Tile> tiles = {},
41                            int64 element_size_in_bits = 0);
42 
43   // Similar to MakeLayout, but take indices in reverse order.
44   static Layout MakeLayoutFromMajorToMinor(
45       absl::Span<const int64> major_to_minor);
46 
47   // Returns a layout with descending ((i.e. {n, n-1, ..., 0}) minor-to-major
48   // dimensions.
49   static Layout MakeDescendingLayout(int64 rank);
50 
51   // Creates a sparse layout with the given maximum number of elements. (This is
52   // a convenience function for protobuf construction.)
53   static Layout MakeSparseLayout(int64 max_sparse_elements);
54 
55   // Returns default layout for the given shape.
56   static Layout GetDefaultLayoutForShape(const Shape& shape);
57 
58   // Helper functions that create default layouts for various ranks.
59   static Layout GetDefaultLayoutForRank(int64 rank);
60   static Layout GetDefaultLayoutForR2();
61   static Layout GetDefaultLayoutForR3();
62   static Layout GetDefaultLayoutForR4();
63 
64   // Sets the default layout on the Shape.
65   static void SetToDefaultLayout(Shape* shape);
66 
67   // Returns a shape with the same dimensions as `shape` but with the default
68   // layout.
69   static Shape GetWithDefaultLayout(const Shape& shape);
70 
71   // Sets the layouts of all Shapes within the given ProgramShape to the
72   // default.
73   static void SetToDefaultLayout(ProgramShape* program_shape);
74 
75   // Validates that the layout within the given shape is correct. The check
76   // is performed for all subshapes as well. If missing layouts are allowed
77   // the check does not fail on array shapes without layouts.
78   static Status ValidateLayoutInShape(const Shape& shape,
79                                       bool allow_missing_layouts = false);
80 
81   // Validates that the provided layout satisfies invariants for the given
82   // shape.
83   static Status ValidateLayoutForShape(const Layout& layout,
84                                        const Shape& shape);
85 
86   // Clears the layout in the given Shape. After this function is called,
87   // HasLayout will return false for the shape.
88   static void ClearLayout(Shape* shape);
89 
90   // Clears the layout on all Shapes within the given ProgramShape.
91   static void ClearLayout(ProgramShape* program_shape);
92 
93   // Returns whether the given Shape is an array and has a dense format layout.
94   static bool IsDenseArray(const Shape& shape);
95 
96   // Returns whether the given Layout has a dense format.
97   static bool IsDense(const Layout& layout);
98 
99   // Returns whether the layout is monotonic and dim 0 is minor in the layout.
100   // * R0 and R1: this is always trivially true.
101   // * R2+: equivalent to column-major. Dimension 0 is the minor, dimension 1 is
102   //        more major, and so on until dimension N-1 which is the major.
103   static bool IsMonotonicWithDim0Minor(const Layout& layout);
104 
105   // Returns whether the layout is monotonic and dim 0 is major in the layout.
106   // * R0 and R1: this is always trivially true.
107   // * R2+: equivalent to row-major. Dimension 0 is the major, dimension 1 is
108   //        more minor, and so on until dimension N-1 which is the minor.
109   static bool IsMonotonicWithDim0Major(const Layout& layout);
110 
111   // Returns whether the given Shape is an array (i.e. not a tuple) and has a
112   // sparse format layout.
113   static bool IsSparseArray(const Shape& shape);
114 
115   // Returns whether the given Layout has a sparse format.
116   static bool IsSparse(const Layout& layout);
117 
118   // Returns the maximum number of elements that can be stored in a sparse
119   // layout.
120   static int64 MaxSparseElements(const Layout& layout);
121 
122   // Returns whether the given shape has a layout. For tuple shapes, true is
123   // returned only if all elements have layouts.
124   static bool HasLayout(const Shape& shape);
125 
126   // Returns whether all Shapes within the given ProgramShape have layouts.
127   static bool HasLayout(const ProgramShape& program_shape);
128 
129   // Returns whether lhs and rhs are identical.
130   static bool Equal(const Layout& lhs, const Layout& rhs);
131 
132   // Returns the minor_to_major array for the given Shape.  Requires that the
133   // shape is an array and has a dense layout.
134   static absl::Span<const int64> MinorToMajor(const Shape& shape);
135   static absl::Span<const int64> MinorToMajor(const Layout& layout);
136 
137   // Major(0) is the most major logical dimension number, Major(1) is the
138   // second-most-major logical dimension number and so on.
139   //
140   // This can be used to translate physical dimension numbers to logical
141   // dimension numbers. Assume that we are numbering the physical dimensions so
142   // that the most major physical dimension has physical dimension number 0 and
143   // so on. Then a physical dimension number p corresponds to the logical
144   // dimension number Major(p). So this function could also be called
145   // PhysicalToLogical().
146   //
147   // As an example, consider physical dimension number 0, which by definition is
148   // the most major. Then Major(0) is the most major logical dimension, so Major
149   // maps the physical dimension number 0 to the most major logical dimension
150   // number Major(0).
151   static int64 Major(const Layout& layout, int64 physical_dimension_number);
152 
153   // Minor(0) is the most minor logical dimension number, minor(1) is the
154   // second-most-minor logical dimension number and so on.
155   static int64 Minor(const Layout& layout, int64 physical_dimension_number);
156 
157   // Returns the inverse mapping of the Major() function. More precisely, return
158   // a vector v such that if l == Major(p), then v[l] == p.
159   //
160   // This can be used to translate logical dimension numbers into physical
161   // dimension numbers. Assume that we are numbering the physical dimensions so
162   // that the most major physical dimension has physical dimension number 0 and
163   // so on. Then a logical dimension number l corresponds to the physical
164   // dimension number MakeLogicalToPhysical(layout)[l].
165   //
166   // As an example, consider physical dimension number 0, which by definition is
167   // the most major. Then l := Major(0) is the most major logical dimension. If
168   // v is the vector returned from this function, then v[l] == 0. So v maps the
169   // most major logical dimension l to the physical dimension number 0.
170   static std::vector<int64> MakeLogicalToPhysical(const Layout& layout);
171 
172   // Returns a human-readable string that represents the given layout.
173   static string HumanString(const Layout& layout);
174 
175   // Copies the layout from 'src' to 'dst'. Recursively copies layouts of
176   // tuples.  'src' and 'dst' need not be compatible but the two shapes must
177   // have the same tuple structure (if any) and arrays must have the same
178   // rank. within the shapes must have the same number of dimensions.
179   static Status CopyLayoutBetweenShapes(const Shape& src, Shape* dst);
180 
181   // Returns true if the layouts of lhs and rhs are equal, false
182   // otherwise. Recursively compares layouts of tuples.
183   //
184   // lhs and rhs need not be compatible to have the same layout but the two
185   // shapes must have the same tuple structure (if any) and arrays must have the
186   // same rank. Element type is ignored.
187   static bool LayoutsInShapesEqual(const Shape& lhs, const Shape& rhs);
188 
189   // Returns whether the given dimensions are consecutive in the given layout,
190   // not necessarily in the order given.
191   static bool AreDimensionsConsecutive(const Layout& layout,
192                                        absl::Span<const int64> dims);
193 
194   // Compute a hash for `layout`.
195   static size_t Hash(const Layout& layout);
196 
197  private:
198   TF_DISALLOW_COPY_AND_ASSIGN(LayoutUtil);
199 };
200 
201 }  // namespace xla
202 
203 #endif  // TENSORFLOW_COMPILER_XLA_LAYOUT_UTIL_H_
204