1 #ifndef CAFFE2_CORE_TENSOR_H_ 2 #define CAFFE2_CORE_TENSOR_H_ 4 #include "caffe2/core/storage.h" 5 #include "caffe2/core/tensor_impl.h" 7 #include <ATen/core/UndefinedTensorImpl.h> 8 #include <c10/util/intrusive_ptr.h> 9 #include "ATen/core/Tensor.h" 10 #include <c10/core/TensorOptions.h> 11 #include <c10/core/Tensor.h> 27 enum Unsafe { IDoWantAliasing };
28 Tensor(
const Tensor& other, Unsafe _) : impl_(other.getIntrusivePtr()) {}
34 void enforce_invariants();
54 operator bool()
const {
55 return impl_.defined();
62 Tensor UnsafeSharedInstance()
const {
63 return Tensor(*
this, IDoWantAliasing);
75 c10::computeTensorTypeId(
at::device(device).layout(
at::kStrided)),
100 explicit Tensor(
const vector<int>& dims, DeviceType type)
121 : impl_(
std::move(tensor.getIntrusivePtr())) {
122 enforce_invariants();
126 return at::Tensor::wrap_tensor_impl(impl_);
130 return at::Tensor::wrap_tensor_impl(std::move(impl_));
140 enforce_invariants();
151 bool is_same(
const Tensor& other)
const noexcept {
152 return impl_ == other.impl_;
175 Tensor x(sizes(), GetDevice());
176 if (!dtype_initialized()) {
177 C10_LOG_EVERY_MS(WARNING, 1000) <<
178 "Cloning a tensor that don't have a data type (did you call mutable_data<T> on the tensor?)";
181 storage_initialized(),
182 "Cloning a tensor that has no content and has size > 0");
184 x.impl_->set_storage(storage());
186 x.impl_->set_sizes_and_strides(sizes(), strides());
190 DeviceType GetDeviceType()
const {
214 src.impl_->is_contiguous(),
215 "Right now only copy of contiguous source Tensor is supported.");
217 src.impl_->storage_initialized(),
218 "Cannot copy from an uninitialized Tensor");
220 if (src.impl_.get() == impl_.get()) {
228 if (impl_->
dtype() != src.impl_->dtype()) {
231 impl_->set_storage(at::Storage::create_legacy(impl_->
device_type(), src.impl_->dtype()));
233 impl_->
Resize(src.impl_->sizes());
235 if (impl_->
numel() > 0) {
239 "In CopyFrom source and dest tensors must both be CPU for " 240 "non-POD copy, but dest tensor was ",
243 src.impl_->device_type() == ::at::DeviceType::CPU,
244 "In CopyFrom source and dest tensors must both be CPU for " 245 "non-POD copy, but src tensor was ",
246 src.impl_->device_type());
276 void ExtendTo(int64_t num,
float growthPct)
const {
277 CAFFE_ENFORCE_GE_WITH_CALLER(impl_->
dim(), 1);
278 CAFFE_ENFORCE_GE_WITH_CALLER(growthPct, 0);
279 Extend(num - impl_->
size(0), growthPct);
282 void Extend(int64_t num,
float growthPct)
const {
283 impl_.get()->
Extend(num, growthPct);
294 CAFFE_ENFORCE_WITH_CALLER(
296 "Right now ShrinkTo is only supported on contiguous Tensor.");
297 CAFFE_ENFORCE_WITH_CALLER(impl_->
dim() >= 1,
"Tensor must be at least 1D");
298 CAFFE_ENFORCE_WITH_CALLER(
299 outer_dim <= impl_->size(0),
300 "New outer dimension must be smaller than current.");
303 "Can't call ShrinkTo on shared storage, please call Resize instead.");
304 impl_.get()->
set_size(0, outer_dim);
308 void ReserveSpace(
const T& outer_dim)
const {
312 template <
typename... Ts>
313 void Resize(Ts... dim_source)
const {
314 impl_.get()->
Resize(dim_source...);
323 CAFFE_ENFORCE_WITH_CALLER(
324 src_tensor.is_contiguous(),
325 "Right now ResizeLike is only supported for contiguous Tensor.");
326 if (impl_ != src_tensor.impl_) {
327 impl_.get()->
Resize(src_tensor.sizes());
331 inline void Reshape(
const vector<int64_t>& dims)
const {
335 inline void Reshape(
const vector<int>& dims)
const {
339 inline void FreeMemory()
const {
349 std::stringstream ss;
350 ss <<
"A Tensor of item size " << impl_->
storage().itemsize() <<
" and type " 351 << impl_->
dtype().
name() <<
" and dimension (";
352 for (
int d : impl_->
sizes()) {
360 void ShareData(
const Tensor& src)
const {
361 impl_.get()->
ShareData(*src.impl_.get());
373 template <
typename T>
377 MemoryDeleter d =
nullptr)
const {
378 ShareExternalPointer((
void*)src, caffe2::TypeMeta::Make<T>(), capacity, d);
381 template <
typename T>
382 void ShareExternalPointer(
at::DataPtr&& data_ptr,
size_t capacity = 0)
const {
383 ShareExternalPointer(std::move(data_ptr), caffe2::TypeMeta::Make<T>(), capacity);
386 void ShareExternalPointer(
390 MemoryDeleter d =
nullptr)
const {
391 CAFFE_ENFORCE_WITH_CALLER(
393 "Right now ShareExternalPointer is only supported for contiguous Tensor.");
394 CAFFE_ENFORCE_WITH_CALLER(
395 data_type.
id() != caffe2::TypeIdentifier::uninitialized(),
396 "To share with a raw external pointer you need to pass in an " 397 "initialized data_type(TypeMeta).");
398 impl_.get()->ShareExternalPointer(
402 void ShareExternalPointer(
406 impl_.get()->ShareExternalPointer(std::move(data_ptr), data_type, capacity);
414 bool defined()
const {
423 return impl_->
data();
426 template <
typename T>
427 inline T* data()
const {
428 return impl_.get()->
data<
T>();
431 inline void* raw_mutable_data(
const TypeMeta& meta)
const {
445 const auto& data_type = impl_->
dtype();
446 CAFFE_ENFORCE_WITH_CALLER(
447 data_type.
id() != caffe2::TypeIdentifier::uninitialized(),
448 "Calling raw_mutable_data() without meta, but the current meta is " 450 return raw_mutable_data(data_type);
453 template <
typename T>
454 inline T* mutable_data()
const {
477 return impl_->
numel();
484 return impl_->
numel();
491 return impl_->
storage().itemsize();
500 return impl_->
numel() * itemsize();
504 return impl_.get()->
sizes();
507 inline int64_t size_from_dim(
int k)
const {
511 inline int64_t size_to_dim(
int k)
const {
512 return size_to_dim_(k, impl_->
sizes());
515 inline int64_t size_between_dim(
int k,
int l)
const {
516 return size_between_dim_(k, l, impl_->
sizes());
531 return canonical_axis_index_(axis_index, impl_->
dim());
534 inline int64_t stride(int64_t dim)
const {
535 return impl_.get()->
stride(dim);
542 inline bool is_contiguous()
const {
549 template <
typename T>
551 return impl_->
storage().IsType<
T>();
558 return impl_->
dtype();
566 return impl_->
dtype();
576 inline int dim32(
const int i)
const {
578 CAFFE_ENFORCE_LT_WITH_CALLER(i, static_cast<int>(impl_->
dim()),
"Exceeding ndim limit");
579 CAFFE_ENFORCE_GE_WITH_CALLER(i, 0,
"Cannot have negative dimension index");
581 auto s = impl_->
size(i);
582 CAFFE_ENFORCE_LT_WITH_CALLER(s, std::numeric_limits<int>::max());
583 return static_cast<int>(s);
586 inline int64_t size(
const int i)
const {
587 return impl_->
size(i);
591 inline int64_t dim(
const int i)
const {
592 return impl_->
size(i);
599 const Storage& storage()
const {
603 bool storage_initialized()
const {
607 bool dtype_initialized()
const {
619 CAFFE2_API
void ReinitializeAndCopyFrom(
625 CAFFE_DECLARE_PREALLOCATED_KNOWN_TYPE(12,
Tensor)
629 constexpr
int k_limit_default_ = 1000;
635 typedef TypeMeta (*TypeCall)(
const void*);
640 typedef vector<int64_t> (*TensorInfoCall)(
643 DeviceOption* device);
645 void RegisterTensorInfoFunction(
TypeIdentifier id, TensorInfoCall c);
648 void TensorVectorResize(
649 std::vector<Tensor>& tensors,
662 template <
typename T>
664 Tensor r = empty(dims, at::device(CPU).dtype<T>());
665 CAFFE_ENFORCE_EQ(values.
size(), r.numel());
667 context.CopyItemsFromCPU(
668 r.dtype(), values.
size(), values.data(), r.mutable_data<
T>());
675 const std::string& tensor_name =
"",
676 const std::string& file_name =
"",
677 int limit = k_limit_default_);
681 void Print(
const Tensor& tensor);
683 void PrintMeta(
const Tensor& tensor);
685 string MetaStr(
const Tensor& tensor);
690 std::unique_ptr<std::ofstream> log_file_;
691 std::string tensor_name_;
695 void TensorPrinter::Print(
const Tensor& tensor) {
696 std::stringstream values_stream;
699 int total_count =
static_cast<int>(std::min(tensor.numel(), int64_t(limit_)));
701 const T* tensor_data = tensor.template data<T>();
702 for (
int i = 0; i < total_count - 1; ++i) {
703 values_stream << tensor_data[i] <<
",";
707 values_stream << tensor_data[total_count - 1];
711 (*log_file_) << MetaStr(tensor) << values_stream.str() << std::endl;
714 LOG(INFO) << MetaStr(tensor) << values_stream.str();
719 #endif // CAFFE2_CORE_TENSOR_H_ virtual int64_t dim() const
Return the number of dimensions of this tensor.
T * data() const
Return a typed data pointer to the actual data which this tensor refers to.
This is a minimal Tensor class for use in c10 code.
int64_t size() const
(To be deprecated) Returns the size (i.e.
bool is_variable() const
True if a tensor is a variable.
virtual void set_size(int64_t dim, int64_t new_size)
Change the size at some dimension.
virtual int64_t size(int64_t d) const
Return the size of a tensor at some dimension.
size_t itemsize() const
Return the number of bytes each item takes in the tensor.
void * raw_mutable_data(const caffe2::TypeMeta &meta)
Returns a mutable raw pointer of the underlying storage.
void * raw_mutable_data() const
Returns a mutable raw pointer of the underlying storage.
void ReinitializeTensor(Tensor *tensor, at::IntArrayRef dims, at::TensorOptions options)
Reinitialize a Tensor to given dims and options if necessary, note that this will not do anything if ...
Tensor Alias() const
Clone self as a Tensor that share the same Storage, that is, both Tensors are views on the same Stora...
const caffe2::TypeMeta & dtype() const
Returns the TypeMeta of a tensor, which describes what data type it is (e.g., int, float, ...)
virtual int64_t numel() const
The number of elements in a tensor.
virtual bool is_contiguous() const
Whether or not a tensor is laid out in contiguous memory.
void Resize(Ts...dim_source)
Resizes a tensor.
void ShrinkTo(int64_t outer_dim) const
Shrinks the outer-most dimension to given size, keeping the data.
virtual IntArrayRef sizes() const
Return a reference to the sizes of this tensor.
int64_t numel() const
Returns the number of items of the tensor.
std::vector< int64_t > ToVectorint64_t(ArrayRef< int > src)
A utility function to convert vector<int> to vector<int64_t>.
void Extend(int64_t num, float growthPct)
Extends the outer-most dimension of this tensor by num elements, preserving the existing data...
A type id is a unique id for a given C++ type.
void ShareData(const TensorImpl &src)
Shares the data with another tensor.
void ShareExternalPointer(T *src, size_t capacity=0, MemoryDeleter d=nullptr) const
Shares the data with an externally managed pointer.
The CPU Context, representing the bare minimum of what a Context class in Caffe2 should implement...
const TypeMeta & dtype() const
Returns the TypeMeta object associated with the current data type.
int64_t size_from_dim_(int k, IntArrayRef dims)
Return product of all dimensions starting from k.
T * mutable_data()
Returns a typed pointer of the underlying storage.
The low-level representation of a tensor, which contains a pointer to a storage (which contains the a...
bool IsType() const
Checks if the tensor content is of the given data type.
size_t itemsize() const
Return the size of a single element of this tensor in bytes.
Tensor(at::IntArrayRef dims, DeviceType type)
Creates a tensor of the given dimension.
void CopyFrom(const Tensor &src, bool async=false)
Copies the data from a source tensor, with a contex provided to carry out the underlying memcpy opera...
size_t nbytes() const
Returns the total number of bytes of the storage.
Represents a a compute device on which a tensor is located.
void FreeMemory()
Release whatever memory the tensor was holding but keep size and type information.
bool dtype_initialized() const noexcept
True if a tensor is dtype initialized.
constexpr size_t size() const
size - Get the array size.
bool storage_initialized() const noexcept
True if a tensor is storage initialized.
Tensor(const at::Tensor &tensor)
Mutual conversion with at::Tensor.
Tensor(at::Device device)
Creates a tensor of the given device type.
A global dictionary that holds information about what Caffe2 modules have been loaded in the current ...
const TypeMeta & meta() const
(To be deprecated) Returns the TypeMeta object associated with the current data type.
void ExtendTo(int64_t num, float growthPct) const
Extend the outer-most dimension of this tensor to dimension of num.
Tensor TensorCPUFromValues(at::IntArrayRef dims, at::ArrayRef< T > values)
Creates a CPU tensor, and fills its contents with the given values.
int ndim() const
(To be deprecated) Returns the number of dimensions of the data.
void ReserveSpace(const T &outer_dim)
Reserve space for the underlying tensor.
virtual int64_t storage_offset() const
Return the offset in number of elements into the storage that this tensor points to.
int dim() const
Returns the number of dimensions of the data.
string DebugString() const
A utility function to print the debug string for the tensor.
int canonical_axis_index(int axis_index) const
Returns the 'canonical' version of a (usually) user-specified axis, allowing for negative indexing (e...
To register your own kernel for an operator, do in one (!) cpp file: C10_REGISTER_KERNEL(OperatorHand...
Flush-To-Zero and Denormals-Are-Zero mode.
void Reshape(const std::vector< int64_t > &dims)
Resizes the tensor without touching underlying storage.
Tensor(C10Tensor tensor)
Mutual conversion with C10Tensor.
void ResizeLike(const Tensor &src_tensor) const
Resize the tensor like the source tensor.
int dim32(const int i) const
Returns the i-th dimension of the tensor in int.
DeviceType device_type() const
The device type of a Tensor, e.g., DeviceType::CPU or DeviceType::CUDA.
void * raw_data() const
Returns a raw void* pointer of the underlying storage.
Tensor(const Tensor &src, DeviceType type)
: Create a Tensor of at::DeviceType type and initialize it with src Tensor
virtual int64_t stride(int64_t d) const
Return the stride of a tensor at some dimension.
Device GetDevice() const
The device of a Tensor; e.g., Device(kCUDA, 1) (the 1-index CUDA device).
virtual const Storage & storage() const
Return the underlying storage of a Tensor.
virtual IntArrayRef strides() const
Return a reference to the strides of this tensor.