forked from ROCm/pytorch
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathStorageImpl.h
225 lines (189 loc) · 5.66 KB
/
StorageImpl.h
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
#pragma once
#include <ATen/core/Allocator.h>
#include <ATen/core/ScalarType.h>
#include <ATen/core/ScalarTypeUtils.h>
#include <ATen/core/intrusive_ptr.h>
namespace at {
struct Type;
struct CAFFE2_API StorageImpl : public c10::intrusive_ptr_target {
public:
StorageImpl(
caffe2::TypeMeta data_type,
int64_t numel,
at::DataPtr data_ptr,
at::Allocator* allocator,
bool resizable)
: data_type_(data_type),
data_ptr_(std::move(data_ptr)),
numel_(numel),
resizable_(resizable),
allocator_(allocator) {
if (numel > 0) {
if (data_type_.id() == caffe2::TypeIdentifier::uninitialized()) {
AT_ERROR(
"Constructing a storage with meta of unknown type and non-zero numel");
}
}
}
StorageImpl(
caffe2::TypeMeta data_type,
int64_t numel,
at::Allocator* allocator,
bool resizable)
: StorageImpl(
data_type,
numel,
allocator->allocate(data_type.itemsize() * numel),
allocator,
resizable) {}
explicit StorageImpl(at::Device device)
: StorageImpl(device, caffe2::TypeMeta()) {}
StorageImpl(at::Device device, caffe2::TypeMeta data_type)
: StorageImpl(data_type, 0, at::DataPtr(nullptr, device), nullptr, true) {
}
StorageImpl& operator=(StorageImpl&& other) = default;
StorageImpl& operator=(const StorageImpl&) = delete;
StorageImpl() = delete;
StorageImpl(StorageImpl&& other) = default;
StorageImpl(StorageImpl&) = delete;
StorageImpl(const StorageImpl&) = delete;
~StorageImpl() = default;
void reset() {
data_ptr_.clear();
numel_ = 0;
}
template <typename T>
inline bool IsType() const {
return data_type_.Match<T>();
}
template <typename T>
inline T* data() const {
// TODO: This is bad: it means storage.data<T>() calls only work on
// T that are valid ScalarType. FIXME!
auto data_type_T = at::scalarTypeToDataType(at::CTypeToScalarType<T>::to());
if (dtype().id() != data_type_T) {
AT_ERROR(
"Attempt to access StorageImpl having data type ",
dtype().id(),
" as data type ",
data_type_T);
}
return unsafe_data<T>();
}
template <typename T>
inline T* unsafe_data() const {
return static_cast<T*>(this->data_ptr_.get());
}
void release_resources() override {
data_ptr_.clear();
}
size_t itemsize() const {
return data_type_.itemsize();
}
Type& type();
size_t capacity() const {
return numel_ * itemsize();
}
int64_t numel() const {
return numel_;
};
// TODO: remove later
void set_numel(int64_t numel) {
numel_ = numel;
};
bool resizable() const {
return resizable_;
};
at::DataPtr& data_ptr() {
return data_ptr_;
};
const at::DataPtr& data_ptr() const {
return data_ptr_;
};
// Returns the previous data_ptr
at::DataPtr set_data_ptr(at::DataPtr&& data_ptr) {
std::swap(data_ptr_, data_ptr);
return std::move(data_ptr);
};
// XXX: TERRIBLE! DONT USE UNLESS YOU HAVE TO! AND EVEN THEN DONT, JUST DONT!
// Setting the data_type will require you to audit many other parts of the
// struct again to make sure it's still valid.
void set_dtype(const caffe2::TypeMeta& data_type) {
int64_t capacity = numel_ * data_type_.itemsize();
data_type_ = data_type;
numel_ = capacity / data_type_.itemsize();
}
// TODO: Return const ptr eventually if possible
void* data() {
return data_ptr_.get();
}
void* data() const {
return data_ptr_.get();
}
at::DeviceType device_type() const {
return data_ptr_.device().type();
}
at::Allocator* allocator() {
return allocator_;
}
const caffe2::TypeMeta& dtype() const {
return data_type_;
}
const at::Allocator* allocator() const {
return allocator_;
};
// You generally shouldn't use this method, but it is occasionally
// useful if you want to override how a tensor will be reallocated,
// after it was already allocated (and its initial allocator was
// set)
void set_allocator(at::Allocator* allocator) {
allocator_ = allocator;
}
Device device() const {
return data_ptr_.device();
}
void set_resizable(bool resizable) {
resizable_ = resizable;
}
/**
* Can only be called when use_count is 1
*/
void UniqueStorageShareExternalPointer(
void* src,
const caffe2::TypeMeta& data_type,
size_t capacity,
DeleterFnPtr d = nullptr) {
UniqueStorageShareExternalPointer(
at::DataPtr(src, src, d, data_ptr_.device()), data_type, capacity);
}
/**
* Can only be called when use_count is 1
*/
void UniqueStorageShareExternalPointer(
at::DataPtr&& data_ptr,
const caffe2::TypeMeta& data_type,
size_t capacity) {
data_type_ = data_type;
// TODO: Use CAFFE_ENFORCE_WITH_CALLER equivalent
// For now causes lots of redefine issues if caffe2/core/logging.h is used
if (data_type_.id() == caffe2::TypeIdentifier::uninitialized()) {
AT_ERROR(
"To share with a raw external pointer you need to have meta "
"already set.");
}
data_ptr_ = std::move(data_ptr);
// NOTE: data_type might change and so it's also possible that capacity
// might not be divisible by itemsize. There is no way for us to keep track
// of the exact capacity if we're not explicity storing is. More conrectely
// capacity() might not return the value that was set here, if itemsize does
// not evenly divide it.
numel_ = capacity / data_type_.itemsize();
}
private:
caffe2::TypeMeta data_type_;
at::DataPtr data_ptr_;
int64_t numel_;
bool resizable_;
at::Allocator* allocator_;
};
} // namespace at