-
Notifications
You must be signed in to change notification settings - Fork 573
Expand file tree
/
Copy pathtensor_util.h
More file actions
228 lines (190 loc) · 8.52 KB
/
Copy pathtensor_util.h
File metadata and controls
228 lines (190 loc) · 8.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
#ifndef XLA_TORCH_XLA_CSRC_TENSOR_UTIL_H_
#define XLA_TORCH_XLA_CSRC_TENSOR_UTIL_H_
#include <ATen/ExpandUtils.h>
#include <torch/csrc/autograd/variable.h>
#include <torch/csrc/lazy/core/hash.h>
#include <string>
#include <vector>
#include "absl/types/span.h"
#include "torch_xla/csrc/device.h"
#include "torch_xla/csrc/runtime/computation_client.h"
#include "torch_xla/csrc/tensor.h"
#include "torch_xla/csrc/unwrap_data.h"
#include "xla/literal.h"
#include "xla/shape.h"
#include "xla/types.h"
namespace torch_xla {
std::vector<int64_t> ComputeShapeStrides(const xla::Shape& shape);
// Converts an XLA literal to an at::Tensor of the given element type.
at::Tensor MakeTensorFromXlaLiteral(const xla::Literal& literal,
at::ScalarType dest_element_type);
// Execution and data transfer are async in PJRT, so TransferFromDevice may
// block until `DataPtr`s are ready. Release the GIL so other threads can
// proceed and unblock any transfers or collective computations.
std::vector<xla::Literal> ReleaseGilAndTransferData(
absl::Span<const torch::lazy::BackendDataPtr> xla_data);
// TODO LTC @wonjoo - Migrate to upstream after Device -> BackendDevice
std::vector<at::Tensor> XlaDataToTensors(
absl::Span<const torch::lazy::BackendDataPtr> xla_data,
absl::Span<const at::ScalarType> dest_element_type);
bool TensorCompare(const at::Tensor& t1, const at::Tensor& t2);
// Uploads an ATEN tensor data to the device and fetches the corresponding
// device data handle.
// TODO LTC @wonjoo - Migrate to upstream after Device -> BackendDevice
torch::lazy::BackendDataPtr TensorToXlaData(
const at::Tensor& tensor, const torch::lazy::BackendDevice& device);
torch::lazy::hash_t TensorHash(const at::Tensor& tensor);
// Retrieves the device data handles by parallel uploading data onto the
// corresponding devices.
// TODO LTC @wonjoo - Migrate to upstream after Device -> BackendDevice
std::vector<torch::lazy::BackendDataPtr> CreateTensorsData(
const std::vector<at::Tensor>& tensors,
const std::vector<std::string>& devices);
std::vector<torch::lazy::BackendDataPtr> CreateGlobalTensorsData(
const std::vector<at::Tensor>& tensors,
const std::vector<XLATensor::ShardingSpecPtr>& shardings,
const std::vector<std::string>& devices,
const xla::Shape local_shape);
// Shard and transfer tensors to devices using `PjRtComputationClient`.
// The client's data transfer to device is asynchronous.
std::vector<torch::lazy::BackendDataPtr> CreateTensorsData(
const std::vector<at::Tensor>& tensors,
const std::vector<XLATensor::ShardingSpecPtr>& sharding_specs,
const std::vector<std::string>& devices);
// Creates an XLA literal out of an ATEN tensor. If shape is specified, that
// shape+layout will be used, otherwise one will be generated out of the ATEN
// tensor shape. The device argument (can be nullptr for the default device)
// tells the API that the created Literal will be sent to such device.
xla::Literal GetTensorLiteral(const at::Tensor& tensor, const xla::Shape* shape,
const torch::lazy::BackendDevice* device);
// If "shape" is a tuple, return the element shapes, otherwise return a
// singleton list containing the original shape.
std::vector<xla::Shape> GetComponentShapes(const xla::Shape& shape);
// Create a shape with "device_type" compatible layout from the given "shape".
xla::Shape MakeShapeWithDeviceLayout(const xla::Shape& shape,
XlaDeviceType hw_type);
// Copy the tensor's data into the destination buffer.
void PopulateTensorBuffer(const at::Tensor& tensor,
const xla::Shape& dest_shape, void* dest_buffer,
size_t dest_buffer_size,
const torch::lazy::BackendDevice& device);
// Create the XLA shape to be used within a lowered XLA computation, to
// represent a given tensor data.
xla::Shape CreateComputationShapeFromTensor(
const at::Tensor& tensor, const torch::lazy::BackendDevice* device);
// Make a compatible dtype for the current device
xla::PrimitiveType GetXlaPrimitiveTypeForCurrentDevice(
xla::PrimitiveType xla_type);
// Converts the given scalar type to an XLA primitive type.
xla::PrimitiveType MakeXlaPrimitiveType(
at::ScalarType scalar_type, const torch::lazy::BackendDevice* device);
// Convert a lazy shape to device dependent xla shape.
xla::Shape MakeXlaShapeFromLazyShape(torch::lazy::Shape shape,
const torch::lazy::BackendDevice& device);
bool RequiresRawTypeCasting(at::ScalarType scalar_type,
const torch::lazy::BackendDevice* device);
xla::PrimitiveType GetShapeDimensionType(
const torch::lazy::BackendDevice* device);
// The following functions are copied from aten/src/ATen/ExpandUtils.h just to
// replace the expand with expand_copy.
// TODO(alanwaketan): Fix the upstream.
inline std::tuple<c10::MaybeOwned<at::Tensor>, c10::MaybeOwned<at::Tensor>,
c10::MaybeOwned<at::Tensor>>
xla_expand_outplace(const at::Tensor& to_expand1, const at::Tensor& to_expand2,
const at::Tensor& to_expand3, const char* api_name) {
at::check_defined({to_expand1, to_expand2, to_expand3}, api_name);
if (to_expand1.sizes().equals(to_expand2.sizes()) &&
to_expand1.sizes().equals(to_expand3.sizes())) {
return std::make_tuple(c10::MaybeOwned<at::Tensor>::borrowed(to_expand1),
c10::MaybeOwned<at::Tensor>::borrowed(to_expand2),
c10::MaybeOwned<at::Tensor>::borrowed(to_expand3));
}
auto expanded_size12 =
at::infer_size_dimvector(to_expand1.sizes(), to_expand2.sizes());
auto expanded_size =
at::infer_size_dimvector(expanded_size12, to_expand3.sizes());
return std::make_tuple(c10::MaybeOwned<at::Tensor>::owned(
at::expand_copy(to_expand1, expanded_size)),
c10::MaybeOwned<at::Tensor>::owned(
at::expand_copy(to_expand2, expanded_size)),
c10::MaybeOwned<at::Tensor>::owned(
at::expand_copy(to_expand3, expanded_size)));
}
inline bool tensor_has_dym_dim(at::Tensor t) {
c10::SymIntArrayRef sym_sizes = t.sym_sizes();
return !c10::asIntArrayRefSlowOpt(sym_sizes).has_value();
}
inline bool tensors_has_dym_dim(at::TensorList tensors) {
for (const at::Tensor& t : tensors) {
if (tensor_has_dym_dim(t)) {
return true;
}
}
return false;
}
inline std::vector<at::Tensor> xla_expand_outplace_symint_helper(
at::TensorList to_expand) {
// expands a list of Tensors; ignores undefined (null) tensors
bool first = true;
at::SymDimVector sym_sizes;
for (const auto i : c10::irange(to_expand.size())) {
if (!to_expand[i].defined()) {
continue;
} else if (first) {
sym_sizes = to_expand[i].sym_sizes();
first = false;
} else {
sym_sizes =
at::infer_size_symdimvector(sym_sizes, to_expand[i].sym_sizes());
}
}
std::vector<at::Tensor> result(to_expand.size());
for (const auto i : c10::irange(to_expand.size())) {
if (!to_expand[i].defined()) {
continue;
} else if (to_expand[i].sym_sizes().equals(sym_sizes)) {
result[i] = to_expand[i];
} else {
result[i] = at::expand_copy_symint(to_expand[i], sym_sizes);
}
}
return result;
}
inline std::vector<at::Tensor> xla_expand_outplace_helper(
at::TensorList to_expand) {
bool first = true;
at::DimVector sizes;
for (const auto i : c10::irange(to_expand.size())) {
if (!to_expand[i].defined()) {
continue;
} else if (first) {
sizes = to_expand[i].sizes();
first = false;
} else {
sizes = at::infer_size_dimvector(sizes, to_expand[i].sizes());
}
}
std::vector<at::Tensor> result(to_expand.size());
for (const auto i : c10::irange(to_expand.size())) {
if (!to_expand[i].defined()) {
continue;
} else if (to_expand[i].sizes().equals(sizes)) {
result[i] = to_expand[i];
} else {
result[i] = at::expand_copy(to_expand[i], sizes);
}
}
return result;
}
inline std::vector<at::Tensor> xla_expand_outplace(at::TensorList to_expand) {
// expands a list of Tensors; ignores undefined (null) tensors
if (tensors_has_dym_dim(to_expand)) {
return xla_expand_outplace_symint_helper(to_expand);
} else {
return xla_expand_outplace_helper(to_expand);
}
}
std::shared_ptr<runtime::ComputationClient::Data> get_data_handle(
const at::Tensor& input);
} // namespace torch_xla
#endif // XLA_TORCH_XLA_CSRC_TENSOR_UTIL_H_