mirror of
https://github.com/pytorch/pytorch.git
synced 2025-10-20 21:14:14 +08:00
123 lines
3.9 KiB
Plaintext
123 lines
3.9 KiB
Plaintext
#if !IS_DISTRIBUTED
|
|
[[
|
|
name: THPTensor_(writeMetadata)
|
|
python_name: _write_metadata
|
|
defined_if: "!IS_DISTRIBUTED"
|
|
only_register: True
|
|
]]
|
|
PyObject * THPTensor_(writeMetadata)(THPTensor *self, PyObject *args)
|
|
{
|
|
if (!args || PyTuple_Size(args) != 1) {
|
|
THPUtils_invalidArguments(args, NULL, "_write_metadata", 1, "a single file object");
|
|
return NULL;
|
|
}
|
|
int fd = PyObject_AsFileDescriptor(PyTuple_GET_ITEM(args, 0));
|
|
if (fd == -1) {
|
|
THPUtils_setError("write_file could not retrieve file descriptor from given object");
|
|
return NULL;
|
|
}
|
|
THPTensor_(writeMetadataRaw)(self->cdata, fd);
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
[[
|
|
name: THPTensor_(newWithMetadataFile)
|
|
python_name: _new_with_metadata_file
|
|
defined_if: "!IS_DISTRIBUTED"
|
|
only_register: True
|
|
method_flags: METH_STATIC
|
|
]]
|
|
PyObject * THPTensor_(newWithMetadataFile)(PyObject *_null, PyObject *args)
|
|
{
|
|
if (!args || PyTuple_Size(args) != 2 ||
|
|
!THPStorage_(Check)(PyTuple_GET_ITEM(args, 1))) {
|
|
THPUtils_invalidArguments(args, NULL, "_new_with_metadata_file", 1,
|
|
"single file object and a storage object");
|
|
return NULL;
|
|
}
|
|
int fd = PyObject_AsFileDescriptor(PyTuple_GET_ITEM(args, 0));
|
|
if (fd == -1) {
|
|
THPUtils_setError("write_file could not retrieve file descriptor from given object");
|
|
return NULL;
|
|
}
|
|
THStorage *storage = ((THPStorage*)PyTuple_GET_ITEM(args, 1))->cdata;
|
|
return THPTensor_(New)(THPTensor_(newWithMetadataFileRaw)(fd, storage));
|
|
}
|
|
#endif
|
|
|
|
|
|
[[
|
|
name: THPTensor_(toNumpy)
|
|
python_name: numpy
|
|
only_register: True
|
|
]]
|
|
// Adapted from fblualib
|
|
PyObject * THPTensor_(toNumpy)(THPTensor *self, PyObject *args) {
|
|
#if !defined(WITH_NUMPY)
|
|
THPUtils_setError("PyTorch was compiled without numpy support\n");
|
|
return NULL;
|
|
#elif defined(THC_GENERIC_FILE)
|
|
THPUtils_setError("can't convert CUDA tensor to numpy (it doesn't support GPU arrays). "
|
|
"Use .cpu() to move the tensor to host memory first.");
|
|
return NULL;
|
|
#elif !defined(NUMPY_TYPE_ENUM)
|
|
THPUtils_setError("numpy conversion for %s is not supported\n", THPUtils_typename(self));
|
|
return NULL;
|
|
#else
|
|
npy_intp zero = 0;
|
|
int ndim;
|
|
npy_intp* sizes_ptr;
|
|
std::unique_ptr<npy_intp[]> sizes;
|
|
std::unique_ptr<npy_intp[]> strides;
|
|
|
|
// Numpy and Torch disagree on empty tensors. In Torch, an empty tensor
|
|
// is a tensor with zero dimensions. In Numpy, a tensor with zero dimensions
|
|
// is a scalar (with one element). So we'll convert an empty Torch tensor
|
|
// to a 1d Numpy tensor of shape [0]. Also see pushTensor in PythonToLua.cpp.
|
|
ndim = THTensor_(nDimension)(LIBRARY_STATE self->cdata);
|
|
if (ndim != 0) {
|
|
|
|
sizes.reset(new npy_intp[ndim]);
|
|
std::copy(self->cdata->size, self->cdata->size + ndim, sizes.get());
|
|
sizes_ptr = sizes.get();
|
|
|
|
if (!THTensor_(isContiguous)(LIBRARY_STATE self->cdata)) {
|
|
strides.reset(new npy_intp[ndim]);
|
|
// Numpy strides use bytes; Torch strides use element counts.
|
|
for (int i = 0; i < ndim; ++i) {
|
|
strides[i] = self->cdata->stride[i] * sizeof(real);
|
|
}
|
|
}
|
|
} else {
|
|
ndim = 1;
|
|
sizes_ptr = &zero;
|
|
}
|
|
|
|
THPObjectPtr array(PyArray_New(
|
|
&PyArray_Type, ndim, sizes_ptr, NUMPY_TYPE_ENUM,
|
|
strides.get(), self->cdata->storage->data + self->cdata->storageOffset,
|
|
0, NPY_ARRAY_ALIGNED | NPY_ARRAY_WRITEABLE | NPY_ARRAY_C_CONTIGUOUS, nullptr));
|
|
if (!array) {
|
|
THPUtils_setError("an error occured during conversion to numpy array");
|
|
return NULL;
|
|
}
|
|
|
|
// Create a PythonStorage object to hold the reference count.
|
|
// PyArray_SetBaseObject steals the reference to the base object.
|
|
// See Note [Numpy memory management]
|
|
Py_INCREF(self);
|
|
if (PyArray_SetBaseObject((PyArrayObject*)(array.get()), (PyObject*)self) == -1) {
|
|
Py_DECREF(self);
|
|
THPUtils_setError("an error occured during conversion to numpy array");
|
|
return NULL;
|
|
}
|
|
|
|
// The storage should never be resized again.
|
|
THStorage_(clearFlag)(self->cdata->storage, TH_STORAGE_RESIZABLE);
|
|
|
|
return array.release();
|
|
#endif
|
|
}
|
|
|
|
|