inline void copy_into_sparse(const SparseTensor& self, const LongTensor& indices, const Tensor& values, bool non_blocking) {
alias_into_sparse(
self,
- self._indices().dispatch_type().copy(indices, non_blocking),
- self._values().dispatch_type().copy(values, non_blocking));
+ indices.to(self._indices().options(), non_blocking, /*copy*/true),
+ values.to(self._values().options(), non_blocking, /*copy*/true));
}
// TODO: put this into the public API
}
Tensor DeprecatedTypeProperties::copy(const Tensor & src, bool non_blocking, c10::optional<Device> to_device) const {
- return getDispatchType().copy(src, non_blocking, to_device);
+ if (to_device) {
+ return src.to(src.options().dtype(scalarType()).device(to_device), non_blocking, /*copy*/true);
+ }
+ return src.to(src.options().dtype(scalarType()), non_blocking, /*copy*/true);
}
std::unique_ptr<Generator> DeprecatedTypeProperties::generator() const {
bool is_alias_of(const at::Tensor& other) const{
return impl_->storage().is_alias_of(other.storage());
}
- Tensor & copy_(const Tensor & src, bool non_blocking=false);
Tensor toType(const DeprecatedTypeProperties & t, bool non_blocking=false) const;
Tensor toType(ScalarType t) const;
Tensor toBackend(Backend b) const;
Tensor clamp_min(Scalar min) const;
Tensor & clamp_min_(Scalar min);
Tensor contiguous() const;
+ Tensor & copy_(const Tensor & src, bool non_blocking=false);
Tensor cos() const;
Tensor & cos_();
Tensor cosh() const;
return toType(type().hip());
}
-inline Tensor & Tensor::copy_(const Tensor & src, bool non_blocking) {
- return dispatch_type().copy_(*this, src, non_blocking);
-}
-
inline Tensor Tensor::toType(ScalarType t) const {
return toType(type().toScalarType(t));
}
inline Tensor Tensor::contiguous() const {
return dispatch_type().contiguous(*this);
}
+inline Tensor & Tensor::copy_(const Tensor & src, bool non_blocking) {
+ return dispatch_type().copy_(*this, src, non_blocking);
+}
inline Tensor Tensor::cos() const {
return dispatch_type().cos(*this);
}
return backendToDeviceType(backend());
}
- virtual Tensor copy(
- const Tensor& src,
- bool non_blocking = false,
- c10::optional<Device> to_device = {}) const = 0;
- virtual Tensor & copy_(Tensor & self, const Tensor & src, bool non_blocking=false) const = 0;
-
virtual void backward(
Tensor& self,
c10::optional<Tensor> gradient,
virtual Tensor clamp_min(const Tensor & self, Scalar min) const = 0;
virtual Tensor & clamp_min_(Tensor & self, Scalar min) const = 0;
virtual Tensor contiguous(const Tensor & self) const = 0;
+ virtual Tensor & copy_(Tensor & self, const Tensor & src, bool non_blocking) const = 0;
virtual Tensor cos(const Tensor & self) const = 0;
virtual Tensor & cos_(Tensor & self) const = 0;
virtual Tensor cosh(const Tensor & self) const = 0;
#include <ATen/ATen.h>
#include <ATen/CPUApplyUtils.h>
#include <ATen/Dispatch.h>
+#include <ATen/ExpandUtils.h>
#include <ATen/NativeFunctions.h>
#include <ATen/native/cpu/CopyKernel.h>
namespace at {
namespace native {
+Tensor & copy_(Tensor & self, const Tensor & src, bool non_blocking) {
+ Tensor b_src;
+ if (self.is_sparse() && src.is_sparse()) {
+ return at::copy_sparse_to_sparse_(self, src, non_blocking);
+ }
+ if (!self.is_sparse() && !src.is_sparse()) {
+ std::tie(b_src) = expand_inplace(self, src, "copy");
+ return s_copy_(self, b_src, non_blocking);
+ }
+ AT_ERROR("copy_() between dense and sparse Tensors is not implemented! Found self type = ",
+ self.type(), " and src type = ", src.type());
+}
+
Tensor& _s_copy__cpu(Tensor& self, const Tensor& src, bool non_blocking) {
if (src.type_id() != CPUTensorId()) {
_s_copy_from(src, self, non_blocking);
}
static inline Tensor to_impl(const Tensor& self, const TensorOptions& options, bool non_blocking) {
- return self.dispatch_type().toBackend(options.backend()).toScalarType(typeMetaToScalarType(options.dtype()))
- .copy(self, non_blocking, options.device());
+ auto r = at::empty(self.sizes(), options);
+ r.copy_(self, non_blocking);
+ return r;
}
Tensor to(const Tensor& self, const TensorOptions& options, bool non_blocking, bool copy) {
// specialized operators for each datatype.
// TODO: remove when we have Type support in the IR
-#define DEFINE_CAST_OP(_1, n, _2) \
- Tensor _cast_##n(const Tensor& self, bool non_blocking) { \
- auto& target_type = self.dispatch_type().toScalarType(ScalarType::n); \
- if (self.dispatch_type() == target_type) \
- return self; \
- return target_type.copy(self, non_blocking); \
+#define DEFINE_CAST_OP(_1, n, _2) \
+ Tensor _cast_##n(const Tensor& self, bool non_blocking) { \
+ if (self.scalar_type() == ScalarType::n) \
+ return self; \
+ return self.to(ScalarType::n, non_blocking); \
}
AT_FORALL_SCALAR_TYPES_AND_BOOL_EXCEPT_QINT(DEFINE_CAST_OP)
- func: conv_transpose3d(Tensor input, Tensor weight, Tensor? bias=None, int[3] stride=1, int[3] padding=0, int[3] output_padding=0, int groups=1, int[3] dilation=1) -> Tensor
+- func: copy_(Tensor(a!) self, Tensor src, bool non_blocking=False) -> Tensor(a!)
+ matches_jit_signature: True
+ variants: function, method
+ device_guard: False
+
- func: s_copy_(Tensor(a!) self, Tensor src, bool non_blocking=False) -> Tensor(a!)
cpu_half: True
cpu_bool: True
bool is_alias_of(const at::Tensor& other) const{
return impl_->storage().is_alias_of(other.storage());
}
- Tensor & copy_(const Tensor & src, bool non_blocking=false);
Tensor toType(const DeprecatedTypeProperties & t, bool non_blocking=false) const;
Tensor toType(ScalarType t) const;
Tensor toBackend(Backend b) const;
return toType(type().hip());
}
-inline Tensor & Tensor::copy_(const Tensor & src, bool non_blocking) {
- return dispatch_type().copy_(*this, src, non_blocking);
-}
-
inline Tensor Tensor::toType(ScalarType t) const {
return toType(type().toScalarType(t));
}
return backendToDeviceType(backend());
}
- virtual Tensor copy(
- const Tensor& src,
- bool non_blocking = false,
- c10::optional<Device> to_device = {}) const = 0;
- virtual Tensor & copy_(Tensor & self, const Tensor & src, bool non_blocking=false) const = 0;
-
virtual void backward(
Tensor& self,
c10::optional<Tensor> gradient,
namespace at {
-Tensor & TypeDefault::copy_(Tensor & self, const Tensor & src, bool non_blocking) const {
- Tensor b_src;
- if (is_sparse()) {
- b_src = src;
- } else {
- std::tie(b_src) = expand_inplace(self, src, "copy");
- }
- return s_copy_(self, b_src, non_blocking);
-}
-
-Tensor TypeDefault::copy(const Tensor & src, bool non_blocking, optional<Device> to_device) const {
- AT_CHECK(src.defined(), "attempt to copy an undefined tensor");
- Tensor r;
- if (is_sparse()) {
- r = at::empty({0}, this->options(to_device));
- } else {
- r = at::empty(src.sizes(), this->options(to_device));
- }
- r.copy_(src, non_blocking);
- return r;
-}
-
void TypeDefault::backward(
Tensor& self,
c10::optional<Tensor> gradient,
Type & toBackend(Backend b) const override;
Type & toScalarType(ScalarType s) const override;
- Tensor copy(const Tensor & src, bool non_blocking=false, optional<Device> to_device={}) const override;
- Tensor & copy_(Tensor & self, const Tensor & src, bool non_blocking=false) const override;
-
void backward(
Tensor& self,
c10::optional<Tensor> gradient,
test_overflow();
if (at::hasCUDA()) {
- auto r = CUDA(Float).copy(next_h);
- ASSERT_TRUE(CPU(Float).copy(r).equal(next_h));
+ auto r = next_h.to(at::Device(kCUDA), kFloat, /*non_blocking*/ false, /*copy*/ true);
+ ASSERT_TRUE(r.to(at::Device(kCPU), kFloat, /*non_blocking*/ false, /*copy*/ true).equal(next_h));
}
ASSERT_NO_THROW(randn({10, 10, 2}, options));
# These functions are written manually in templates/VariableType.cpp
MANUAL_IMPLEMENTATIONS = {
- 'resize_', 'resize_as_', 'detach', 'detach_', 's_copy_', '_s_copy_from'
+ 'resize_', 'resize_as_', 'detach', 'detach_', 'copy_'
}
# These functions we don't want to record for tracing, because we always want
END_HANDLE_TH_ERRORS
}
-static Tensor dispatch_copy_(Tensor & self, const Tensor & other, bool non_blocking) {
- AutoNoGIL no_gil;
- OptionalDeviceGuard device_guard(device_of(self));
- return self.copy_(other, non_blocking);
-}
-
-static PyObject * THPVariable_copy_(PyObject* self, PyObject* args, PyObject* kwargs)
-{
- HANDLE_TH_ERRORS
- static PythonArgParser parser({
- "copy_(Tensor other, bool non_blocking=False)",
- "copy_(Tensor other, bool async=False)|deprecated"
- });
- auto& self_ = reinterpret_cast<THPVariable*>(self)->cdata;
- ParsedArgs<2> parsed_args;
- auto r = parser.parse(args, kwargs, parsed_args);
- return THPVariable_Wrap(dispatch_copy_(self_, r.tensor(0), r.toBool(1)));
- END_HANDLE_TH_ERRORS
-}
-
static double dispatch_to_CDouble(const Tensor & self) {
AutoNoGIL no_gil;
OptionalDeviceGuard device_guard(device_of(self));
{"byte", (PyCFunction)THPVariable_byte, METH_NOARGS, NULL},
{"char", (PyCFunction)THPVariable_char, METH_NOARGS, NULL},
{"contiguous", (PyCFunction)THPVariable_contiguous, METH_NOARGS, NULL},
- {"copy_", (PyCFunction)THPVariable_copy_, METH_VARARGS | METH_KEYWORDS, NULL},
{"cpu", (PyCFunction)THPVariable_cpu, METH_NOARGS, NULL},
{"cuda", (PyCFunction)THPVariable_cuda, METH_VARARGS | METH_KEYWORDS, NULL},
{"dim", (PyCFunction)THPVariable_dim, METH_NOARGS, NULL},
'numpy': ['def numpy(self) -> Any: ...'],
'apply_': ['def apply_(self, callable: Callable) -> Tensor: ...'],
'map_': ['def map_(tensor: Tensor, callable: Callable) -> Tensor: ...'],
- 'copy_': ['def copy_(self, src: Tensor, non_blocking: bool=False) -> Tensor: ...'],
'storage': ['def storage(self) -> Storage: ...'],
'type': ['def type(self, dtype: Union[None, str, _dtype]=None, non_blocking: bool=False)'
' -> Union[str, Tensor]: ...'],
void VariableType::set_data(Tensor & self, Tensor new_data) const {
as_variable_ref(self).set_data(new_data);
}
-Tensor & VariableType::s_copy_(Tensor & self, const Tensor & src, bool non_blocking) const {
+
+Tensor & VariableType::copy_(Tensor & self, const Tensor & src, bool non_blocking) const {
jit::Value* output = nullptr;
if(torch::jit::tracer::isTracing()) {
const jit::tracer::TracingState& state = *jit::tracer::getTracingState();
}
{
at::AutoNonVariableTypeMode non_var_type_mode(true);
- if (self.is_sparse() && src.is_sparse()) baseType->copy_sparse_to_sparse_(self_, src_, non_blocking);
- else if (!self.is_sparse() && !src.is_sparse()) baseType->s_copy_(self_, src_, non_blocking);
- else AT_ERROR("copy_() between dense and sparse Tensors is not implemented! Found self type = ", self.type(), " and src type = ", src.type());
+ baseType->copy_(self_, src_, non_blocking);
}
increment_version(self);
rebase_history(as_variable_ref( self ), std::move(grad_fn));
return self;
}
-Tensor VariableType::_s_copy_from(const Tensor & self, const Tensor & dst, bool non_blocking) const {
- AT_ERROR("copy_from does not support automatic differentiation; use copy_ instead");
-}
-
Tensor & VariableType::resize_(Tensor & self, IntArrayRef size) const {
auto& self_ = unpack(self, "self", 0);
if (as_variable_ref(self).requires_grad()) {
// TODO: What if !grad.is_cuda(), but src_device is CUDA?
// This code is kind of weirdly asymmetric.
if (grad.is_cuda() && grad.device() != src_device) {
- grad_inputs[1] = src_type->copy(grad);
+ grad_inputs[1] = grad.to(
+ src_type->device_type(),
+ src_type->scalarType(),
+ /*non_blocking*/false,
+ /*copy*/true);
} else {
grad_inputs[1] = grad.toType(*src_type);
}
#else
{
#endif
- auto & gpu_type = type.toBackend(type.is_sparse() ? at::Backend::SparseCUDA : at::Backend::CUDA);
if (type.is_cuda()) {
tensors.push_back(tensor);
}
IntArrayRef loop_devices = type.is_cuda() ? devices.slice(1) : devices;
for (auto device : loop_devices) {
_device_guard.set_index(device);
- tensors.push_back(gpu_type.copy(tensor, true));
+ tensors.push_back(tensor.to(
+ kCUDA,
+ type.scalarType(),
+ /*non_blocking*/true,
+ /*copy*/true));
}
}
return tensors;