Caffe2 - C++ API
A deep learning, cross platform ML framework
input_buffer.cpp
1 #include <torch/csrc/autograd/input_buffer.h>
2 
3 #include <torch/csrc/autograd/functions/basic_ops.h>
4 #include <torch/csrc/autograd/input_metadata.h>
5 
6 #include <ATen/DeviceGuard.h>
7 
8 #include <cstddef>
9 #include <utility>
10 #include <vector>
11 
12 namespace torch { namespace autograd {
13 
14 
15 void InputBuffer::add(size_t pos, Variable var) {
16  AT_ASSERT(pos < buffer.size());
17  if (!var.defined()) {
18  return;
19  }
20  auto& old_var = buffer[pos];
21  if (!old_var.defined()) {
22  buffer[pos] = std::move(var);
23  } else {
24  at::OptionalDeviceGuard device_guard(device_of(var));
25  // ATen doesn't route sparse additions correctly...
26  // do dense + sparse in-place if possible
27  if (old_var.is_sparse()) {
28 //storage use_count is a big hammer, but for anything lighter there's an adversarial example with unexpected inplace modification
29  if (!var.is_sparse() && var.is_contiguous() && var.storage().use_count() == 1) {
30  buffer[pos] = var.add_(old_var);
31  } else {
32  buffer[pos] = var + old_var;
33  }
34  } else {
35  if (var.is_sparse() && !old_var.is_sparse() && old_var.is_contiguous() && old_var.storage().use_count() == 1) {
36  buffer[pos] = old_var.add_(var);
37  } else {
38  buffer[pos] = old_var + var;
39  }
40  }
41  }
42 }
43 
44 auto InputBuffer::device() const -> at::Device {
45  // Since we pick the first non-CPU tensor, this won't work with
46  // mixed device-type operations (e.g., an op that is both CUDA
47  // and XLA). This is *incredibly* unlikely, so we don't worry
48  // about it.
49  for (auto& var : buffer) {
50  if (var.defined()) {
51  auto device = var.device();
52  if (device.type() != at::kCPU) {
53  return device;
54  }
55  }
56  }
57  // Only report to the CPU thread if there really were no tensors
58  // from other devices.
59  return at::kCPU;
60 }
61 
62 auto InputBuffer::variables(InputBuffer&& g) -> std::vector<Variable> {
63  std::vector<Variable> result = std::move(g.buffer);
64  return result;
65 }
66 
67 }} // namespace torch::autograd
optional< Device > device_of(Tensor t)
Return the Device of a Tensor, if the Tensor is defined.
Definition: DeviceGuard.h:17
A OptionalDeviceGuard is an RAII class that sets a device to some value on initialization, and resets the device to its original value on destruction.
Definition: DeviceGuard.h:119
Definition: jit_type.h:17
Flush-To-Zero and Denormals-Are-Zero mode.
DeviceType type() const noexcept
Returns the type of device this is.
Definition: Device.h:65