pytorch/torch/csrc/lazy/backend/backend_device.cpp
Brian Hirsh 4a2d2e5e40 Change API type Tensor[] for structured kernels. (#73350)
Partially fixes: #66328

This PR:
- adds support for `ITensorList` to the dispatcher for:
  - computing the dispatch key
  - boxing and unboxing `ITensorList`
- modified the codegen for structured kernels:
  - codegen APIs use `ITensorList` instead of `ArrayRef<Tensor>`

**Changes summary:**

- Signature changes due to the different APIs:
  - dispatcher API (e.g. `BatchingRegistrations.cpp`)
  - C++ API (e.g. `TensorShape.cpp`)
- Miscelaneous functions used by codegen'd functions (e.g. `FunctionalTensorWrapper.*`)
- Dispatcher changes for handling `ITensorList` correctly (e.g. `DispatchKeyExtractor.h`)
- Signature changes of `at::cat` due to the need of `const` inside `TensorBody.h`
- Forward declarations of `ITensorList` (e.g. `MethodOperators.h`)
- Codegen changes, special casing structured kernels (e.g. `gen.py`)

**Short description of structured kernels special casing:**

I introduced, mainly, 5 types of changes to the codegen for generating code depending on
whether the kernel is structured or not:

1. Added a `structured_type_override` flag to the `argument_type` function definition of
the affected APIs (mainly the dispatcher and C++ APIs).
  - `api/cpp.py`, `api/dispatcher.py`, `api/native.py`
2. Added a `structured_type_override` member to the signature
classes (e.g. `CppSignature`), since `FunctionSchema` doesn't really know whether the
function is structured or not
  - `api/types.py`
3. Added a `part_of_structured_group` to `NativeFunction` class, which is just a
convenient function to forward to `structured_type_override` wherever needed
  - `model.py`
4. Appropriately changed the rest of the codegen, whenever it used either the signature
classes or the `arguments` function directly
5. Added a check for `const ITensorList&` type wherever there was a check for `TensorList`
Pull Request resolved: https://github.com/pytorch/pytorch/pull/73350
Approved by: https://github.com/bdhirsh
2022-09-26 21:46:38 +00:00

91 lines
2.5 KiB
C++

#include <torch/csrc/lazy/backend/backend_device.h>
#include <c10/core/Device.h>
#include <c10/util/Exception.h>
#include <c10/util/Optional.h>
#include <c10/util/StringUtil.h>
#include <torch/csrc/lazy/backend/backend_interface.h>
#include <torch/csrc/lazy/core/tensor.h>
namespace torch {
namespace lazy {
BackendDevice::BackendDevice()
: type_(getBackend()->GetDefaultDeviceType()),
ordinal_(getBackend()->GetDefaultDeviceOrdinal()) {}
BackendDevice::BackendDevice(
std::shared_ptr<BackendDeviceType>&& type,
int64_t ordinal)
: type_(std::move(type)), ordinal_(ordinal) {}
int8_t BackendDevice::type() const {
TORCH_INTERNAL_ASSERT(type_);
return type_->type;
}
std::string BackendDevice::toString() const {
TORCH_INTERNAL_ASSERT(type_);
return c10::str(type_->toString(), ordinal_);
}
int BackendDevice::compare(const BackendDevice& rhs) const {
if (type() != rhs.type()) {
return type() < rhs.type() ? -1 : +1;
}
return ordinal_ < rhs.ordinal_ ? -1 : (ordinal_ > rhs.ordinal_ ? +1 : 0);
}
std::ostream& operator<<(std::ostream& os, const BackendDevice& device) {
os << device.toString();
return os;
}
BackendDevice atenDeviceToBackendDevice(const c10::Device& device) {
TORCH_CHECK(device.type() == at::kLazy, device);
int64_t ordinal = device.has_index()
? device.index()
: getBackend()->GetDefaultDeviceOrdinal();
return BackendDevice(getBackend()->GetDefaultDeviceType(), ordinal);
}
// TODO(whc) refactor this: we need to support non 1 on 1 mapping for torch/XLA.
c10::Device backendDeviceToAtenDevice(const BackendDevice& device) {
return c10::Device(at::kLazy, device.ordinal());
}
c10::optional<BackendDevice> GetBackendDevice(at::ITensorListRef tensors) {
for (auto& tensor : tensors) {
if (auto lt = TryGetLtcTensor(tensor)) {
return lt->GetDevice();
}
}
return c10::nullopt;
}
c10::optional<BackendDevice> GetBackendDevice(at::TensorList tensors) {
return GetBackendDevice(at::ITensorListRef(tensors));
}
c10::optional<BackendDevice> GetBackendDevice(const at::Tensor& tensor) {
if (auto lt = TryGetLtcTensor(tensor)) {
return lt->GetDevice();
}
return c10::nullopt;
}
c10::optional<BackendDevice> GetBackendDevice(
const c10::optional<c10::Device> device) {
if (device) {
return c10::make_optional(atenDeviceToBackendDevice(*device));
}
return c10::nullopt;
}
c10::optional<BackendDevice> GetBackendDevice() {
return c10::nullopt;
}
} // namespace lazy
} // namespace torch