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 #ifndef TENSORFLOW_COMPILER_XLA_TESTS_TEST_UTILS_H_
17 #define TENSORFLOW_COMPILER_XLA_TESTS_TEST_UTILS_H_
18 
19 #include <initializer_list>
20 #include <memory>
21 #include <random>
22 
23 #include "absl/memory/memory.h"
24 #include "absl/types/span.h"
25 #include "tensorflow/compiler/xla/layout_util.h"
26 #include "tensorflow/compiler/xla/literal.h"
27 #include "tensorflow/compiler/xla/service/hlo_instructions.h"
28 #include "tensorflow/compiler/xla/service/hlo_module.h"
29 #include "tensorflow/compiler/xla/xla_data.pb.h"
30 #include "tensorflow/core/platform/types.h"
31 
32 namespace xla {
33 
34 // A class which generates pseudorandom numbers of a given type within a given
35 // range. Not cryptographically secure and likely not perfectly evenly
36 // distributed across the range but sufficient for most tests.
37 template <typename NativeT>
38 class PseudorandomGenerator {
39  public:
PseudorandomGenerator(NativeT min_value,NativeT max_value,uint32 seed)40   explicit PseudorandomGenerator(NativeT min_value, NativeT max_value,
41                                  uint32 seed)
42       : min_(min_value), max_(max_value), generator_(seed) {}
43 
44   // Get a pseudorandom value.
get()45   NativeT get() {
46     std::uniform_real_distribution<> distribution;
47     return static_cast<NativeT>(min_ +
48                                 (max_ - min_) * distribution(generator_));
49   }
50 
51  private:
52   NativeT min_;
53   NativeT max_;
54   std::mt19937 generator_;
55 };
56 
57 // Generates fake data in a literal of the given shape, or returns an error
58 // status if the element type is currently unhandled for fake data
59 // generation. See below for documentation of pseudo_random and use_large_range.
60 StatusOr<Literal> MakeFakeLiteral(const Shape& shape, bool pseudo_random = true,
61                                   bool use_large_range = false);
62 
63 // Generates a vector of arguments containing fake data. The number, shape and
64 // layout of the arguments is appropriate for given HLO module.
65 //
66 // A best-effort attempt is made to generate the data in a way which produce
67 // stable computation results across platforms. Specifically:
68 //
69 //  (1) Init values of reductions should be the identity of the reduction
70 //  computation.
71 //
72 //  (2) Indices of dynamic slices and update slices should be in bounds.
73 //
74 //  (3) Keys of key/value sorts should contain no duplicates.
75 //
76 // These constraints are best-effort only.
77 //
78 // If pseudo_random is true, the generated numbers will be generated
79 // deterministically in a pseudo random way unless the values are constrated to
80 // be e.g. init values as above. If pseudo_random is false, the returned values
81 // will be generated in a faster way that yields less interesting data, e.g. the
82 // values may all be just the same value.
83 //
84 // If use_large_range is false, the generated floating point numbers will be
85 // sampled from a small range of possible values. If use_large_range is true,
86 // the generated floating point numbers will be sampled from a uniform-log
87 // distribution of most possible floats, with a small chance to instead be
88 // sampled from a list of special floating point values (such as 0, inf, etc.).
89 //
90 // TODO(b/79942829): Make interesting argument generation fast enough that using
91 // pseudo_random does not save any noticeable amount of time so that the
92 // parameter can be removed.
93 StatusOr<std::vector<Literal>> MakeFakeArguments(HloModule* const module,
94                                                  bool pseudo_random = true,
95                                                  bool use_large_range = false);
96 
97 // Overload which accepts a random number generator. This enables generation of
98 // different random values with sequential calls to MakeFakeArguments by reusing
99 // the same generator.
100 StatusOr<std::vector<Literal>> MakeFakeArguments(HloModule* const module,
101                                                  std::minstd_rand0* engine,
102                                                  bool use_large_range = false);
103 
104 // Check that a given module satisfies various constraints before trying to
105 // execute it.
106 Status VerifyHloModule(HloModule* const module, bool layout_sensitive,
107                        bool allow_mixed_precision);
108 
109 // Creates a dot op with operands 'lhs' and 'rhs' that contracts dimension 1 of
110 // the LHS with dimension 0 of the RHS with no batch dimensions.
111 // Both LHS and the RHS must be of rank 2.
112 std::unique_ptr<HloDotInstruction> CreateCanonicalDot(const Shape& shape,
113                                                       HloInstruction* lhs,
114                                                       HloInstruction* rhs);
115 }  // namespace xla
116 
117 #endif  // TENSORFLOW_COMPILER_XLA_TESTS_TEST_UTILS_H_
118