MCPcopy Create free account
hub / github.com/Oneflow-Inc/oneflow / MakeLocalTensorFromData

Function MakeLocalTensorFromData

oneflow/api/python/utils/tensor_utils.cpp:129–194  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

127}
128
129Maybe<Tensor> MakeLocalTensorFromData(PyObject* data, const Optional<Symbol<DType>>& dtype,
130 const Optional<Symbol<Device>>& device,
131 const bool requires_grad, const bool pin_memory) {
132 bool is_bfloat16_dtype = dtype ? JUST(dtype)->data_type() == DataType::kBFloat16 : false;
133 bool is_cuda_device = device ? JUST(device)->enum_type() == DeviceType::kCUDA : false;
134 if (is_bfloat16_dtype && is_cuda_device) {
135#if CUDA_VERSION < 11000
136 return Error::RuntimeError()
137 << "Cannot create a bfloat16 tensor on gpu under cuda version: 11000";
138#endif // CUDA_VERSION >= 11000
139 }
140 PyArray_Descr* np_dtype =
141 dtype.has_value() && !is_bfloat16_dtype
142 ? PyArray_DescrFromType(JUST(numpy::OFDataTypeToNumpyType(JUST(dtype)->data_type())))
143 : nullptr;
144 // NPY_ARRAY_DEFAULT is NPY_ARRAY_C_CONTIGUOUS | NPY_ARRAY_BEHAVED, so the
145 // array with NPY_ARRAY_DEFAULT flag is C-style contiguous.
146 // NPY_ARRAY_FORCECAST is needed otherwise there will a segfault.
147 //
148 // Even though PyArray_FromAny can cast the input array to the desired dtype
149 // if `dtype` argument is set, it fails to handle the following case:
150 // >> x = [flow.tensor([1, 2])] * 3 <-- x is a list of flow.Tensor
151 // >> y = flow.tensor(x, dtype=flow.float32) <-- returns nullptr
152 // However, the following case without `dtype` argument works well:
153 // >> x = [flow.tensor([1, 2])] * 3
154 // >> y = flow.tensor(x)
155 // So we cast the input array to the desired dtype manually.
156 PyArrayObject* _array = reinterpret_cast<PyArrayObject*>(
157 PyArray_FromAny(data, nullptr, 0, 0,
158 NPY_ARRAY_DEFAULT | NPY_ARRAY_ENSURECOPY | NPY_ARRAY_FORCECAST, nullptr));
159 if (!_array) {
160 return Error::RuntimeError() << "Can not convert input data to a new numpy array.";
161 }
162 // PyArray_FromArray steals a reference to np_dtype object, so no need to decref it.
163 PyObject* array = PyArray_FromArray(
164 _array, np_dtype, NPY_ARRAY_DEFAULT | NPY_ARRAY_ENSURECOPY | NPY_ARRAY_FORCECAST);
165 Py_DECREF(_array);
166 auto* np_arr = reinterpret_cast<PyArrayObject*>(array);
167 const npy_intp* dims_ptr = PyArray_SHAPE(np_arr);
168 const Shape shape(DimVector(dims_ptr, dims_ptr + PyArray_NDIM(np_arr)));
169 DataType np_data_type = JUST(numpy::GetOFDataTypeFromNpArray(np_arr));
170
171 Symbol<Device> device_;
172 if (device) {
173 device_ = JUST(device);
174 } else {
175 device_ = JUST(Device::New("cpu"));
176 }
177 std::shared_ptr<Tensor> tensor =
178 JUST(functional::Empty(shape, JUST(DType::Get(np_data_type)), device_,
179 /*requires_grad=*/false, /*pin_memory=*/pin_memory));
180 if (device_->enum_type() != DeviceType::kMeta) {
181 JUST(CopyLocalTensorFromUntypedArray(tensor, array));
182 }
183
184 Py_DECREF(array);
185 if (dtype && JUST(dtype)->data_type() != np_data_type) {
186 tensor = JUST(functional::To(tensor, JUST(dtype), false));

Callers 2

operator()Method · 0.85
operator()Method · 0.85

Calls 12

OFDataTypeToNumpyTypeFunction · 0.85
GetOFDataTypeFromNpArrayFunction · 0.85
GetFunction · 0.85
GetDefaultDTypeFunction · 0.85
enum_typeMethod · 0.80
NewFunction · 0.50
data_typeMethod · 0.45
has_valueMethod · 0.45
is_floating_pointMethod · 0.45
dtypeMethod · 0.45
set_requires_gradMethod · 0.45

Tested by

no test coverage detected