未验证 提交 e32c4375 编写于 作者: L LiYuRio 提交者: GitHub

Construct dist tensor (#54425)

* construct dist tensor

* move constructor to header
上级 38f38a91
...@@ -43,6 +43,8 @@ using phi::distributed::auto_parallel::Machine; ...@@ -43,6 +43,8 @@ using phi::distributed::auto_parallel::Machine;
using phi::distributed::auto_parallel::ProcessMesh; using phi::distributed::auto_parallel::ProcessMesh;
using phi::distributed::auto_parallel::TensorDistAttr; using phi::distributed::auto_parallel::TensorDistAttr;
PyTypeObject *g_tensor_dist_attr_pytype = nullptr;
static inline const ProcessMesh *get_tensor_process_mesh( static inline const ProcessMesh *get_tensor_process_mesh(
const TensorDistAttr &self) { const TensorDistAttr &self) {
if (self.process_mesh().empty()) { if (self.process_mesh().empty()) {
...@@ -225,8 +227,11 @@ void BindAutoParallel(py::module *m) { ...@@ -225,8 +227,11 @@ void BindAutoParallel(py::module *m) {
py::arg("memo")) py::arg("memo"))
.def("__str__", &DeviceMesh::to_string); .def("__str__", &DeviceMesh::to_string);
py::class_<TensorDistAttr>(*m, "TensorDistAttr") py::class_<TensorDistAttr, std::shared_ptr<TensorDistAttr>> py_dist_attr(
.def(py::init<>()) *m, "TensorDistAttr");
g_tensor_dist_attr_pytype =
reinterpret_cast<PyTypeObject *>(py_dist_attr.ptr());
py_dist_attr.def(py::init<>())
.def(py::init([](const VarDesc &var_desc) { .def(py::init([](const VarDesc &var_desc) {
auto shape = auto shape =
paddle::distributed::auto_parallel::get_tensor_shape(&var_desc); paddle::distributed::auto_parallel::get_tensor_shape(&var_desc);
......
...@@ -41,6 +41,14 @@ limitations under the License. */ ...@@ -41,6 +41,14 @@ limitations under the License. */
#include "paddle/fluid/pybind/exception.h" #include "paddle/fluid/pybind/exception.h"
#include "paddle/fluid/pybind/tensor_py.h" #include "paddle/fluid/pybind/tensor_py.h"
#include "paddle/phi/core/string_tensor.h" #include "paddle/phi/core/string_tensor.h"
#ifdef PADDLE_WITH_DISTRIBUTE
#include "paddle/phi/core/distributed/auto_parallel/dist_attr.h"
#include "paddle/phi/core/distributed/auto_parallel/dist_tensor.h"
using phi::distributed::auto_parallel::DistTensor;
using phi::distributed::auto_parallel::TensorDistAttr;
#endif
namespace paddle { namespace paddle {
namespace pybind { namespace pybind {
...@@ -60,6 +68,52 @@ PyObject* TensorNew(PyTypeObject* type, PyObject* args, PyObject* kwargs) { ...@@ -60,6 +68,52 @@ PyObject* TensorNew(PyTypeObject* type, PyObject* args, PyObject* kwargs) {
return obj; return obj;
} }
#ifdef PADDLE_WITH_DISTRIBUTE
void EmptyDistTensorInitializer(
TensorObject* self,
const std::string& name,
const paddle::platform::Place& place,
const std::shared_ptr<TensorDistAttr>& dist_attr,
bool persistable = false,
int stop_gradient = -1,
framework::proto::VarType::Type dtype =
paddle::framework::proto::VarType::FP32,
const std::vector<int>& dims = {0}) {
auto ddims = phi::make_ddim(dims);
self->tensor.set_name(name);
auto autograd_meta = egr::EagerUtils::autograd_meta(&(self->tensor));
autograd_meta->SetPersistable(persistable);
if (stop_gradient != -1) {
autograd_meta->SetStopGradient(static_cast<bool>(stop_gradient));
}
std::shared_ptr<DistTensor> dist_tensor = nullptr;
if (dims.size() == 1 && dims[0] == 0) {
std::shared_ptr<phi::Allocation> allocation_ptr = nullptr;
dist_tensor = std::make_shared<DistTensor>(
allocation_ptr,
phi::DenseTensorMeta(paddle::framework::TransToPhiDataType(dtype),
ddims),
dist_attr);
} else {
dist_tensor = std::make_shared<DistTensor>(
std::make_shared<phi::Allocation>(),
phi::DenseTensorMeta(paddle::framework::TransToPhiDataType(dtype),
ddims),
dist_attr);
}
self->tensor.set_impl(dist_tensor);
if (!autograd_meta->GetMutableGradNode()) {
autograd_meta->SetGradNode(
std::make_shared<egr::GradNodeAccumulation>(autograd_meta));
VLOG(3) << "Tensor(" << name
<< ") have not GradNode, add GradNodeAccumulation"
<< autograd_meta->GradNode() << " for it.";
}
}
#endif
// TODO(jiabin): Overload this once we need more constructor in Python // TODO(jiabin): Overload this once we need more constructor in Python
void EmptyTensorInitializer(TensorObject* self, void EmptyTensorInitializer(TensorObject* self,
const std::string& name, const std::string& name,
...@@ -82,6 +136,7 @@ void EmptyTensorInitializer(TensorObject* self, ...@@ -82,6 +136,7 @@ void EmptyTensorInitializer(TensorObject* self,
// TODO(jiabin): Maybe support LOD later // TODO(jiabin): Maybe support LOD later
std::shared_ptr<phi::DenseTensor> dense_tensor = nullptr; std::shared_ptr<phi::DenseTensor> dense_tensor = nullptr;
if (dims.size() == 1 && dims[0] == 0) { if (dims.size() == 1 && dims[0] == 0) {
VLOG(0) << "Create dense tensor with dims[0] equal to 0";
std::shared_ptr<phi::Allocation> allocation_ptr = nullptr; std::shared_ptr<phi::Allocation> allocation_ptr = nullptr;
dense_tensor = std::make_shared<phi::DenseTensor>( dense_tensor = std::make_shared<phi::DenseTensor>(
allocation_ptr, allocation_ptr,
...@@ -129,6 +184,48 @@ void EmptyStringTensorInitializer(TensorObject* self, ...@@ -129,6 +184,48 @@ void EmptyStringTensorInitializer(TensorObject* self,
self->tensor.set_impl(string_tensor); self->tensor.set_impl(string_tensor);
} }
#ifdef PADDLE_WITH_DISTRIBUTE
void InitDistTensorWithNumpyValue(TensorObject* self,
const py::object& array,
const paddle::platform::Place& place,
bool zero_copy = false) {
PADDLE_ENFORCE_EQ(
self->tensor.defined(),
true,
paddle::platform::errors::Fatal(
"Calling InitDistTensorWithNumpyValue of Eager Tensor without "
"EmptyDistTensorInitializer is "
"forbidden. Please check your code and make sure you new a "
"eager tensor before init it with NumPy."));
DistTensor* dist_tensor_ptr =
static_cast<DistTensor*>(self->tensor.impl().get());
phi::DenseTensor* impl_ptr =
static_cast<phi::DenseTensor*>(dist_tensor_ptr->mutable_value());
if (platform::is_cpu_place(place)) {
SetTensorFromPyArray<platform::CPUPlace>(impl_ptr, array, place, zero_copy);
} else if (platform::is_xpu_place(place)) {
SetTensorFromPyArray<platform::XPUPlace>(impl_ptr, array, place, zero_copy);
} else if (platform::is_gpu_place(place)) {
SetTensorFromPyArray<platform::CUDAPlace>(
impl_ptr, array, place, zero_copy);
} else if (platform::is_cuda_pinned_place(place)) {
SetTensorFromPyArray<platform::CUDAPinnedPlace>(
impl_ptr, array, place, zero_copy);
} else if (platform::is_custom_place(place)) {
SetTensorFromPyArray<platform::CustomPlace>(
impl_ptr, array, place, zero_copy);
} else {
PADDLE_THROW(platform::errors::InvalidArgument(
"Place should be one of "
"CPUPlace/XPUPlace/CUDAPlace/CUDAPinnedPlace/CustomPlace"));
}
// TODO(dev): dist_tensor meta is not equal to dense tensor meta
dist_tensor_ptr->set_meta(impl_ptr->meta());
}
#endif
void InitTensorWithNumpyValue(TensorObject* self, void InitTensorWithNumpyValue(TensorObject* self,
const py::object& array, const py::object& array,
const paddle::platform::Place& place, const paddle::platform::Place& place,
...@@ -143,6 +240,7 @@ void InitTensorWithNumpyValue(TensorObject* self, ...@@ -143,6 +240,7 @@ void InitTensorWithNumpyValue(TensorObject* self,
"eager tensor before init it with NumPy.")); "eager tensor before init it with NumPy."));
phi::DenseTensor* impl_ptr = phi::DenseTensor* impl_ptr =
static_cast<phi::DenseTensor*>(self->tensor.impl().get()); static_cast<phi::DenseTensor*>(self->tensor.impl().get());
if (platform::is_cpu_place(place)) { if (platform::is_cpu_place(place)) {
SetTensorFromPyArray<platform::CPUPlace>(impl_ptr, array, place, zero_copy); SetTensorFromPyArray<platform::CPUPlace>(impl_ptr, array, place, zero_copy);
} else if (platform::is_xpu_place(place)) { } else if (platform::is_xpu_place(place)) {
...@@ -186,6 +284,39 @@ void InitStringTensorWithNumpyValue(TensorObject* self, const py::object& obj) { ...@@ -186,6 +284,39 @@ void InitStringTensorWithNumpyValue(TensorObject* self, const py::object& obj) {
} }
} }
#ifdef PADDLE_WITH_DISTRIBUTE
void InitDistTensorWithTensor(
TensorObject* self,
const paddle::Tensor& src,
const paddle::platform::Place& place,
const std::string& name,
const std::shared_ptr<TensorDistAttr>& dist_attr) {
PADDLE_ENFORCE(src.is_dense_tensor(),
paddle::platform::errors::InvalidArgument(
"DistTensor can only initialize by DenseTensor"));
self->tensor.set_name(name);
if (place == src.place()) {
std::shared_ptr<phi::DenseTensor> tensor =
std::static_pointer_cast<phi::DenseTensor>(src.impl());
self->tensor.set_impl(std::make_shared<DistTensor>(tensor, dist_attr));
VLOG(4) << "Same place, do ShareDataWith";
} else {
std::shared_ptr<phi::DenseTensor> tensor =
std::static_pointer_cast<phi::DenseTensor>(
src.copy_to(place, true).impl());
self->tensor.set_impl(std::make_shared<DistTensor>(tensor, dist_attr));
VLOG(4) << "Different place, do TensorCopy";
}
if (src.get_autograd_meta()) {
egr::EagerUtils::autograd_meta(&(self->tensor))
->SetPersistable(
egr::EagerUtils::unsafe_autograd_meta(src)->Persistable());
} else {
egr::EagerUtils::autograd_meta(&(self->tensor))->SetPersistable(false);
}
}
#endif
void InitTensorWithTensor(TensorObject* self, void InitTensorWithTensor(TensorObject* self,
const paddle::Tensor& src, const paddle::Tensor& src,
const paddle::platform::Place& place, const paddle::platform::Place& place,
...@@ -283,6 +414,25 @@ paddle::platform::Place ParsePlace( ...@@ -283,6 +414,25 @@ paddle::platform::Place ParsePlace(
return place; return place;
} }
#ifdef PADDLE_WITH_DISTRIBUTE
std::shared_ptr<TensorDistAttr> ParseDistAttrArgs(
std::unordered_map<std::string, PyObject*> kws_map,
std::unordered_map<std::string, Py_ssize_t> kw_order_map,
PyObject* args,
bool flag_kwargs,
Py_ssize_t args_num) {
std::shared_ptr<TensorDistAttr> dist_attr = nullptr;
if (kw_order_map["dist_attr"] <= args_num) {
dist_attr = CastPyArg2DistAttr(
PyTuple_GET_ITEM(args, kw_order_map["dist_attr"] - 1),
kw_order_map["dist_attr"] - 1);
} else if (flag_kwargs && kws_map["dist_attr"] != NULL) {
dist_attr = CastPyArg2DistAttr(kws_map["dist_attr"], 0);
}
return dist_attr;
}
#endif
// boolean arguments: zero_copy, stop_gradient, persistable // boolean arguments: zero_copy, stop_gradient, persistable
int ParseBooleanArgs(std::string key, int ParseBooleanArgs(std::string key,
std::unordered_map<std::string, PyObject*> kws_map, std::unordered_map<std::string, PyObject*> kws_map,
...@@ -347,13 +497,13 @@ void AutoInitTensorByPyArray(TensorObject* py_tensor_ptr, ...@@ -347,13 +497,13 @@ void AutoInitTensorByPyArray(TensorObject* py_tensor_ptr,
// kw_order_map's value is the position of the arguments respectively. // kw_order_map's value is the position of the arguments respectively.
// If u want to update this constructor with new arguments, // If u want to update this constructor with new arguments,
// need to update this map and to add or change related code. // need to update this map and to add or change related code.
std::unordered_map<std::string, Py_ssize_t> kw_order_map{ std::unordered_map<std::string, Py_ssize_t> kw_order_map{{"value", 1},
{"value", 1},
{"place", 2}, {"place", 2},
{"persistable", 3}, {"persistable", 3},
{"zero_copy", 4}, {"zero_copy", 4},
{"name", 5}, {"name", 5},
{"stop_gradient", 6}}; {"stop_gradient", 6},
{"dist_attr", 7}};
py::object numpy_value = py::object(); py::object numpy_value = py::object();
paddle::platform::Place place = paddle::platform::Place place =
...@@ -378,6 +528,18 @@ void AutoInitTensorByPyArray(TensorObject* py_tensor_ptr, ...@@ -378,6 +528,18 @@ void AutoInitTensorByPyArray(TensorObject* py_tensor_ptr,
stop_gradient = ParseBooleanArgs( stop_gradient = ParseBooleanArgs(
"stop_gradient", kws_map, kw_order_map, args, flag_kwargs, args_num); "stop_gradient", kws_map, kw_order_map, args, flag_kwargs, args_num);
#ifdef PADDLE_WITH_DISTRIBUTE
std::shared_ptr<TensorDistAttr> dist_attr =
ParseDistAttrArgs(kws_map, kw_order_map, args, flag_kwargs, args_num);
if (dist_attr) {
EmptyDistTensorInitializer(
py_tensor_ptr, act_name, place, dist_attr, persistable, stop_gradient);
InitDistTensorWithNumpyValue(py_tensor_ptr, numpy_value, place, zero_copy);
return;
}
#endif
EmptyTensorInitializer( EmptyTensorInitializer(
py_tensor_ptr, act_name, place, persistable, stop_gradient); py_tensor_ptr, act_name, place, persistable, stop_gradient);
InitTensorWithNumpyValue(py_tensor_ptr, numpy_value, place, zero_copy); InitTensorWithNumpyValue(py_tensor_ptr, numpy_value, place, zero_copy);
...@@ -399,7 +561,7 @@ void AutoInitTensorByTensor(TensorObject* py_tensor_ptr, ...@@ -399,7 +561,7 @@ void AutoInitTensorByTensor(TensorObject* py_tensor_ptr,
// If u want to update this constructor with new arguments, // If u want to update this constructor with new arguments,
// need to update this map and to add or change related code. // need to update this map and to add or change related code.
std::unordered_map<std::string, Py_ssize_t> kw_order_map{ std::unordered_map<std::string, Py_ssize_t> kw_order_map{
{"value", 1}, {"place", 2}, {"name", 3}}; {"value", 1}, {"place", 2}, {"name", 3}, {"dist_attr", 4}};
paddle::platform::Place place = paddle::platform::Place place =
egr::Controller::Instance().GetExpectedPlace(); egr::Controller::Instance().GetExpectedPlace();
...@@ -408,6 +570,11 @@ void AutoInitTensorByTensor(TensorObject* py_tensor_ptr, ...@@ -408,6 +570,11 @@ void AutoInitTensorByTensor(TensorObject* py_tensor_ptr,
place = ParsePlace(kws_map, kw_order_map, args, flag_kwargs, args_num); place = ParsePlace(kws_map, kw_order_map, args, flag_kwargs, args_num);
act_name = ParseName(kws_map, kw_order_map, args, flag_kwargs, args_num); act_name = ParseName(kws_map, kw_order_map, args, flag_kwargs, args_num);
#ifdef PADDLE_WITH_DISTRIBUTE
std::shared_ptr<TensorDistAttr> dist_attr =
ParseDistAttrArgs(kws_map, kw_order_map, args, flag_kwargs, args_num);
#endif
if (init_by_egr_tensor) { if (init_by_egr_tensor) {
paddle::Tensor src_tensor; paddle::Tensor src_tensor;
if (kw_order_map["value"] <= args_num) { if (kw_order_map["value"] <= args_num) {
...@@ -426,7 +593,16 @@ void AutoInitTensorByTensor(TensorObject* py_tensor_ptr, ...@@ -426,7 +593,16 @@ void AutoInitTensorByTensor(TensorObject* py_tensor_ptr,
"way.")); "way."));
} }
} }
#ifdef PADDLE_WITH_DISTRIBUTE
if (dist_attr) {
InitDistTensorWithTensor(
py_tensor_ptr, src_tensor, place, act_name, dist_attr);
} else {
InitTensorWithTensor(py_tensor_ptr, src_tensor, place, act_name);
}
#else
InitTensorWithTensor(py_tensor_ptr, src_tensor, place, act_name); InitTensorWithTensor(py_tensor_ptr, src_tensor, place, act_name);
#endif
} else { } else {
// init by framework tensor // init by framework tensor
phi::DenseTensor src_tensor; phi::DenseTensor src_tensor;
...@@ -545,7 +721,8 @@ void AutoInitStringTensorByStringTensor( ...@@ -545,7 +721,8 @@ void AutoInitStringTensorByStringTensor(
* ** persistable: bool, * ** persistable: bool,
* ** zero_copy: bool, * ** zero_copy: bool,
* ** name: std::string, * ** name: std::string,
* ** stop_gradient: bool) * ** stop_gradient: bool,
* ** dist_attr: phi::distributed::TensorDistAttr)
* 4. * 4.
* def __init__ ( * def __init__ (
* ** value: ndarray) * ** value: ndarray)
...@@ -558,7 +735,8 @@ void AutoInitStringTensorByStringTensor( ...@@ -558,7 +735,8 @@ void AutoInitStringTensorByStringTensor(
* def __init__ ( * def __init__ (
* ** tensor: Tensor, * ** tensor: Tensor,
* ** place: paddle::platform::Place, * ** place: paddle::platform::Place,
* ** name: std::string) * ** name: std::string,
* ** dist_attr: phi::distributed::TensorDistAttr)
* 7. (multi-place) (should have at least one parameter, one parameter similar * 7. (multi-place) (should have at least one parameter, one parameter similar
* to case 5, zero parameter equals to case 1.) * to case 5, zero parameter equals to case 1.)
* def __init__ ( * def __init__ (
...@@ -583,6 +761,7 @@ int TensorInit(PyObject* self, PyObject* args, PyObject* kwargs) { ...@@ -583,6 +761,7 @@ int TensorInit(PyObject* self, PyObject* args, PyObject* kwargs) {
PyObject* kw_dims = NULL; PyObject* kw_dims = NULL;
PyObject* kw_dtype = NULL; PyObject* kw_dtype = NULL;
PyObject* kw_type = NULL; PyObject* kw_type = NULL;
PyObject* kw_dist_attr = NULL;
// the keywords argument // the keywords argument
static char* kwlist[] = {const_cast<char*>("value"), static char* kwlist[] = {const_cast<char*>("value"),
...@@ -594,6 +773,7 @@ int TensorInit(PyObject* self, PyObject* args, PyObject* kwargs) { ...@@ -594,6 +773,7 @@ int TensorInit(PyObject* self, PyObject* args, PyObject* kwargs) {
const_cast<char*>("dims"), const_cast<char*>("dims"),
const_cast<char*>("dtype"), const_cast<char*>("dtype"),
const_cast<char*>("type"), const_cast<char*>("type"),
const_cast<char*>("dist_attr"),
NULL}; NULL};
// 'O' Store a Python object (without any conversion) in a C object pointer, // 'O' Store a Python object (without any conversion) in a C object pointer,
...@@ -604,7 +784,7 @@ int TensorInit(PyObject* self, PyObject* args, PyObject* kwargs) { ...@@ -604,7 +784,7 @@ int TensorInit(PyObject* self, PyObject* args, PyObject* kwargs) {
// which enhance case2, case3, case4, case5, case6, case7. // which enhance case2, case3, case4, case5, case6, case7.
bool flag_ = PyArg_ParseTupleAndKeywords(args, bool flag_ = PyArg_ParseTupleAndKeywords(args,
kwargs, kwargs,
"|OOOOOOOOO", "|OOOOOOOOOO",
kwlist, kwlist,
&kw_value, &kw_value,
&kw_place, &kw_place,
...@@ -614,7 +794,8 @@ int TensorInit(PyObject* self, PyObject* args, PyObject* kwargs) { ...@@ -614,7 +794,8 @@ int TensorInit(PyObject* self, PyObject* args, PyObject* kwargs) {
&kw_stop_gradient, &kw_stop_gradient,
&kw_dims, &kw_dims,
&kw_dtype, &kw_dtype,
&kw_type); &kw_type,
&kw_dist_attr);
// helper map // helper map
std::unordered_map<std::string, PyObject*> kws_map{ std::unordered_map<std::string, PyObject*> kws_map{
...@@ -626,7 +807,8 @@ int TensorInit(PyObject* self, PyObject* args, PyObject* kwargs) { ...@@ -626,7 +807,8 @@ int TensorInit(PyObject* self, PyObject* args, PyObject* kwargs) {
{"stop_gradient", kw_stop_gradient}, {"stop_gradient", kw_stop_gradient},
{"dims", kw_dims}, {"dims", kw_dims},
{"dtype", kw_dtype}, {"dtype", kw_dtype},
{"type", kw_type}}; {"type", kw_type},
{"dist_attr", kw_dist_attr}};
PADDLE_ENFORCE_EQ(flag_, PADDLE_ENFORCE_EQ(flag_,
true, true,
...@@ -636,7 +818,7 @@ int TensorInit(PyObject* self, PyObject* args, PyObject* kwargs) { ...@@ -636,7 +818,7 @@ int TensorInit(PyObject* self, PyObject* args, PyObject* kwargs) {
"sure you are on the right way. " "sure you are on the right way. "
"The expected arguments as follow: (" "The expected arguments as follow: ("
"value, place, persistable, zero_copy, " "value, place, persistable, zero_copy, "
"name, stop_gradient, dims, dtype, type)")); "name, stop_gradient, dims, dtype, type, dist_attr)"));
PADDLE_ENFORCE_NOT_NULL( PADDLE_ENFORCE_NOT_NULL(
self, self,
......
...@@ -62,6 +62,9 @@ typedef SSIZE_T ssize_t; ...@@ -62,6 +62,9 @@ typedef SSIZE_T ssize_t;
#include "paddle/phi/core/flags.h" #include "paddle/phi/core/flags.h"
#include "paddle/phi/core/tensor_utils.h" #include "paddle/phi/core/tensor_utils.h"
#include "paddle/phi/kernels/funcs/math_function.h" #include "paddle/phi/kernels/funcs/math_function.h"
#ifdef PADDLE_WITH_DISTRIBUTE
#include "paddle/phi/core/distributed/auto_parallel/dist_tensor.h"
#endif
PHI_DECLARE_bool(set_to_1d); PHI_DECLARE_bool(set_to_1d);
...@@ -796,6 +799,15 @@ static PyObject* tensor_method_get_underline_tensor(TensorObject* self, ...@@ -796,6 +799,15 @@ static PyObject* tensor_method_get_underline_tensor(TensorObject* self,
auto* tensor = static_cast<phi::DenseTensor*>(self->tensor.impl().get()); auto* tensor = static_cast<phi::DenseTensor*>(self->tensor.impl().get());
VLOG(6) << "tensor: " << tensor->IsInitialized(); VLOG(6) << "tensor: " << tensor->IsInitialized();
return ToPyObject(tensor); return ToPyObject(tensor);
} else if (self->tensor.is_dist_tensor()) {
#ifdef PADDLE_WITH_DISTRIBUTE
auto* tensor = static_cast<phi::distributed::auto_parallel::DistTensor*>(
self->tensor.impl().get());
VLOG(6) << "dist tensor: " << tensor->IsInitialized();
return ToPyObject(tensor);
#else
RETURN_PY_NONE
#endif
} else { } else {
RETURN_PY_NONE RETURN_PY_NONE
} }
...@@ -1697,6 +1709,17 @@ static PyObject* tensor_method_is_dense(TensorObject* self, ...@@ -1697,6 +1709,17 @@ static PyObject* tensor_method_is_dense(TensorObject* self,
EAGER_CATCH_AND_THROW_RETURN_NULL EAGER_CATCH_AND_THROW_RETURN_NULL
} }
static PyObject* tensor_method_is_dist(TensorObject* self,
PyObject* args,
PyObject* kwargs) {
EAGER_TRY
if (!self->tensor.defined()) {
return ToPyObject(false);
}
return ToPyObject(self->tensor.is_dist_tensor());
EAGER_CATCH_AND_THROW_RETURN_NULL
}
static PyObject* tensor_method_is_sparse(TensorObject* self, static PyObject* tensor_method_is_sparse(TensorObject* self,
PyObject* args, PyObject* args,
PyObject* kwargs) { PyObject* kwargs) {
...@@ -2051,6 +2074,10 @@ PyMethodDef variable_methods[] = { ...@@ -2051,6 +2074,10 @@ PyMethodDef variable_methods[] = {
(PyCFunction)(void (*)(void))tensor_method_is_dense, (PyCFunction)(void (*)(void))tensor_method_is_dense,
METH_VARARGS | METH_KEYWORDS, METH_VARARGS | METH_KEYWORDS,
NULL}, NULL},
{"is_dist",
(PyCFunction)(void (*)(void))tensor_method_is_dist,
METH_VARARGS | METH_KEYWORDS,
NULL},
{"_zero_grads", {"_zero_grads",
(PyCFunction)(void (*)(void))tensor__zero_grads, (PyCFunction)(void (*)(void))tensor__zero_grads,
METH_VARARGS | METH_KEYWORDS, METH_VARARGS | METH_KEYWORDS,
......
...@@ -158,6 +158,23 @@ int tensor_properties_set_persistable(TensorObject* self, ...@@ -158,6 +158,23 @@ int tensor_properties_set_persistable(TensorObject* self,
EAGER_CATCH_AND_THROW_RETURN_NEG EAGER_CATCH_AND_THROW_RETURN_NEG
} }
PyObject* tensor_properties_get_dist_attr(TensorObject* self, void* closure) {
EAGER_TRY
if (self->tensor.is_dist_tensor()) {
#ifdef PADDLE_WITH_DISTRIBUTE
phi::distributed::auto_parallel::DistTensor* dist_tensor =
static_cast<phi::distributed::auto_parallel::DistTensor*>(
self->tensor.impl().get());
return ToPyObject(dist_tensor->dist_attr().get());
#else
RETURN_PY_NONE
#endif
} else {
RETURN_PY_NONE
}
EAGER_CATCH_AND_THROW_RETURN_NULL
}
PyObject* tensor_properties_get_shape(TensorObject* self, void* closure) { PyObject* tensor_properties_get_shape(TensorObject* self, void* closure) {
EAGER_TRY EAGER_TRY
std::vector<int64_t> value; std::vector<int64_t> value;
...@@ -311,6 +328,11 @@ struct PyGetSetDef variable_properties[] = { ...@@ -311,6 +328,11 @@ struct PyGetSetDef variable_properties[] = {
// nullptr, // nullptr,
// nullptr}, // nullptr},
{"place", (getter)tensor_properties_get_place, nullptr, nullptr, nullptr}, {"place", (getter)tensor_properties_get_place, nullptr, nullptr, nullptr},
{"dist_attr",
(getter)tensor_properties_get_dist_attr,
nullptr,
nullptr,
nullptr},
{"_place_str", {"_place_str",
(getter)tensor_properties_get_place_str, (getter)tensor_properties_get_place_str,
nullptr, nullptr,
......
...@@ -59,6 +59,9 @@ extern PyTypeObject* g_customplace_pytype; ...@@ -59,6 +59,9 @@ extern PyTypeObject* g_customplace_pytype;
extern PyTypeObject* g_framework_tensor_pytype; extern PyTypeObject* g_framework_tensor_pytype;
extern PyTypeObject* g_framework_lodtensorarray_pytype; extern PyTypeObject* g_framework_lodtensorarray_pytype;
extern PyTypeObject* g_jit_function_pytype; extern PyTypeObject* g_jit_function_pytype;
#ifdef PADDLE_WITH_DISTRIBUTE
extern PyTypeObject* g_tensor_dist_attr_pytype;
#endif
int TensorDtype2NumpyDtype(phi::DataType dtype) { int TensorDtype2NumpyDtype(phi::DataType dtype) {
switch (dtype) { switch (dtype) {
...@@ -540,6 +543,23 @@ platform::Place CastPyArg2Place(PyObject* obj, ssize_t arg_pos) { ...@@ -540,6 +543,23 @@ platform::Place CastPyArg2Place(PyObject* obj, ssize_t arg_pos) {
return place; return place;
} }
#ifdef PADDLE_WITH_DISTRIBUTE
using phi::distributed::auto_parallel::TensorDistAttr;
std::shared_ptr<TensorDistAttr> CastPyArg2DistAttr(PyObject* obj,
ssize_t arg_pos) {
if (PyObject_IsInstance(
obj, reinterpret_cast<PyObject*>(g_tensor_dist_attr_pytype))) {
return ::pybind11::handle(obj).cast<std::shared_ptr<TensorDistAttr>>();
} else {
PADDLE_THROW(platform::errors::InvalidArgument(
"argument (position %d) must be "
"TensorDistAttr, but got %s",
arg_pos + 1,
reinterpret_cast<PyTypeObject*>(obj->ob_type)->tp_name));
}
}
#endif
phi::DenseTensor CastPyArg2FrameworkTensor(PyObject* obj, ssize_t arg_pos) { phi::DenseTensor CastPyArg2FrameworkTensor(PyObject* obj, ssize_t arg_pos) {
if (PyObject_TypeCheck(obj, g_framework_tensor_pytype)) { if (PyObject_TypeCheck(obj, g_framework_tensor_pytype)) {
return ::pybind11::handle(obj).cast<phi::DenseTensor>(); return ::pybind11::handle(obj).cast<phi::DenseTensor>();
...@@ -838,6 +858,21 @@ PyObject* ToPyObject(const phi::DenseTensor* value) { ...@@ -838,6 +858,21 @@ PyObject* ToPyObject(const phi::DenseTensor* value) {
return obj.ptr(); return obj.ptr();
} }
#ifdef PADDLE_WITH_DISTRIBUTE
PyObject* ToPyObject(const phi::distributed::auto_parallel::DistTensor* value) {
auto obj = ::pybind11::cast(value, py::return_value_policy::reference);
obj.inc_ref();
return obj.ptr();
}
PyObject* ToPyObject(
const phi::distributed::auto_parallel::TensorDistAttr* value) {
auto obj = ::pybind11::cast(value, py::return_value_policy::reference);
obj.inc_ref();
return obj.ptr();
}
#endif
PyObject* ToPyObject(const phi::SelectedRows* value) { PyObject* ToPyObject(const phi::SelectedRows* value) {
auto obj = ::pybind11::cast(value, py::return_value_policy::reference); auto obj = ::pybind11::cast(value, py::return_value_policy::reference);
obj.inc_ref(); obj.inc_ref();
......
...@@ -37,6 +37,11 @@ typedef SSIZE_T ssize_t; ...@@ -37,6 +37,11 @@ typedef SSIZE_T ssize_t;
#include "paddle/utils/pybind.h" #include "paddle/utils/pybind.h"
#include "pybind11/pybind11.h" #include "pybind11/pybind11.h"
#include "pybind11/stl.h" #include "pybind11/stl.h"
#ifdef PADDLE_WITH_DISTRIBUTE
#include "paddle/phi/core/distributed/auto_parallel/dist_attr.h"
#include "paddle/phi/core/distributed/auto_parallel/dist_tensor.h"
#endif
namespace paddle { namespace paddle {
class CustomOpKernelContext; class CustomOpKernelContext;
namespace framework { namespace framework {
...@@ -106,6 +111,11 @@ PyObject* ToPyObject(const std::vector<std::vector<paddle::Tensor>>& value, ...@@ -106,6 +111,11 @@ PyObject* ToPyObject(const std::vector<std::vector<paddle::Tensor>>& value,
bool return_py_none_if_not_initialize = false); bool return_py_none_if_not_initialize = false);
PyObject* ToPyObject(const platform::Place& value); PyObject* ToPyObject(const platform::Place& value);
PyObject* ToPyObject(const phi::DenseTensor* value); PyObject* ToPyObject(const phi::DenseTensor* value);
#ifdef PADDLE_WITH_DISTRIBUTE
PyObject* ToPyObject(const phi::distributed::auto_parallel::DistTensor* value);
PyObject* ToPyObject(
const phi::distributed::auto_parallel::TensorDistAttr* value);
#endif
PyObject* ToPyObject(const phi::SelectedRows* value); PyObject* ToPyObject(const phi::SelectedRows* value);
PyObject* ToPyObject(const paddle::framework::proto::VarType::Type& dtype); PyObject* ToPyObject(const paddle::framework::proto::VarType::Type& dtype);
PyObject* ToPyObject(const paddle::framework::proto::VarType& type); PyObject* ToPyObject(const paddle::framework::proto::VarType& type);
...@@ -287,6 +297,11 @@ paddle::DataType CastPyArg2DataType(PyObject* obj, ...@@ -287,6 +297,11 @@ paddle::DataType CastPyArg2DataType(PyObject* obj,
const std::string& op_type, const std::string& op_type,
ssize_t arg_pos); ssize_t arg_pos);
#ifdef PADDLE_WITH_DISTRIBUTE
std::shared_ptr<phi::distributed::auto_parallel::TensorDistAttr>
CastPyArg2DistAttr(PyObject* obj, ssize_t arg_pos);
#endif
paddle::optional<paddle::Tensor> GetOptionalTensorFromArgs( paddle::optional<paddle::Tensor> GetOptionalTensorFromArgs(
const std::string& op_type, const std::string& op_type,
const std::string& arg_name, const std::string& arg_name,
......
...@@ -174,6 +174,9 @@ limitations under the License. */ ...@@ -174,6 +174,9 @@ limitations under the License. */
#include "paddle/phi/kernels/autotune/cache.h" #include "paddle/phi/kernels/autotune/cache.h"
#include "paddle/phi/kernels/autotune/switch_autotune.h" #include "paddle/phi/kernels/autotune/switch_autotune.h"
#include "pybind11/stl.h" #include "pybind11/stl.h"
#ifdef PADDLE_WITH_DISTRIBUTE
#include "paddle/phi/core/distributed/auto_parallel/dist_tensor.h"
#endif
PHI_DECLARE_bool(use_mkldnn); PHI_DECLARE_bool(use_mkldnn);
PHI_DECLARE_bool(use_shm_cache); PHI_DECLARE_bool(use_shm_cache);
...@@ -1021,6 +1024,17 @@ void BindTensor(pybind11::module &m) { // NOLINT ...@@ -1021,6 +1024,17 @@ void BindTensor(pybind11::module &m) { // NOLINT
})); }));
#endif #endif
#ifdef PADDLE_WITH_DISTRIBUTE
using phi::distributed::auto_parallel::DistTensor;
py::class_<DistTensor>(m, "DistTensor")
.def(
"get_tensor",
[](DistTensor &self) { return self.mutable_value(); },
py::return_value_policy::reference)
.def("numel",
[](DistTensor &self) -> int64_t { return self.value().numel(); });
#endif
py::class_<phi::SelectedRows>(m, "SelectedRows") py::class_<phi::SelectedRows>(m, "SelectedRows")
.def("__init__", .def("__init__",
[](phi::SelectedRows &instance) { [](phi::SelectedRows &instance) {
......
...@@ -219,6 +219,13 @@ class PADDLE_API Tensor final { ...@@ -219,6 +219,13 @@ class PADDLE_API Tensor final {
*/ */
bool is_dense_tensor() const; bool is_dense_tensor() const;
/**
* @brief Determine whether tensor is DistTensor
*
* @return bool
*/
bool is_dist_tensor() const;
/** /**
* @brief Determine whether tensor is SelectedRows * @brief Determine whether tensor is SelectedRows
* *
......
...@@ -28,6 +28,10 @@ limitations under the License. */ ...@@ -28,6 +28,10 @@ limitations under the License. */
#include "paddle/phi/core/sparse_coo_tensor.h" #include "paddle/phi/core/sparse_coo_tensor.h"
#include "paddle/phi/core/sparse_csr_tensor.h" #include "paddle/phi/core/sparse_csr_tensor.h"
#ifdef PADDLE_WITH_DISTRIBUTE
#include "paddle/phi/core/distributed/auto_parallel/dist_tensor.h"
#endif
// TODO(chenweihang): split Key, Kernel, Factory into diff files // TODO(chenweihang): split Key, Kernel, Factory into diff files
#include "paddle/phi/core/kernel_factory.h" #include "paddle/phi/core/kernel_factory.h"
......
...@@ -34,6 +34,9 @@ limitations under the License. */ ...@@ -34,6 +34,9 @@ limitations under the License. */
#include "paddle/phi/core/tensor_base.h" #include "paddle/phi/core/tensor_base.h"
#include "paddle/phi/core/tensor_meta.h" #include "paddle/phi/core/tensor_meta.h"
#include "paddle/phi/core/tensor_utils.h" #include "paddle/phi/core/tensor_utils.h"
#ifdef PADDLE_WITH_DISTRIBUTE
#include "paddle/phi/core/distributed/auto_parallel/dist_tensor.h"
#endif
namespace paddle { namespace paddle {
...@@ -128,6 +131,13 @@ DataLayout Tensor::layout() const { return impl_->layout(); } ...@@ -128,6 +131,13 @@ DataLayout Tensor::layout() const { return impl_->layout(); }
bool Tensor::is_dense_tensor() const { bool Tensor::is_dense_tensor() const {
return phi::DenseTensor::classof(impl_.get()); return phi::DenseTensor::classof(impl_.get());
} }
bool Tensor::is_dist_tensor() const {
#ifdef PADDLE_WITH_DISTRIBUTE
return phi::distributed::auto_parallel::DistTensor::classof(impl_.get());
#else
return false;
#endif
}
bool Tensor::is_selected_rows() const { bool Tensor::is_selected_rows() const {
return phi::SelectedRows::classof(impl_.get()); return phi::SelectedRows::classof(impl_.get());
} }
......
...@@ -29,6 +29,11 @@ limitations under the License. */ ...@@ -29,6 +29,11 @@ limitations under the License. */
namespace phi { namespace phi {
class DenseTensorUtils; class DenseTensorUtils;
namespace distributed {
namespace auto_parallel {
class DistTensor;
} // namespace auto_parallel
} // namespace distributed
/// \brief The Dense tensor stores values in a contiguous sequential block /// \brief The Dense tensor stores values in a contiguous sequential block
/// of memory where all values are represented. Tensors or multi-dimensional /// of memory where all values are represented. Tensors or multi-dimensional
...@@ -181,6 +186,7 @@ class DenseTensor : public TensorBase, ...@@ -181,6 +186,7 @@ class DenseTensor : public TensorBase,
private: private:
friend class DenseTensorUtils; friend class DenseTensorUtils;
friend class phi::distributed::auto_parallel::DistTensor;
protected: protected:
DenseTensorMeta meta_; DenseTensorMeta meta_;
......
proto_library(auto_parallel_proto SRCS auto_parallel.proto) proto_library(auto_parallel_proto SRCS auto_parallel.proto)
collect_srcs(core_srcs SRCS device_mesh.cc process_mesh.cc dist_attr.cc collect_srcs(
dist_mapper.cc) core_srcs
SRCS
device_mesh.cc
process_mesh.cc
dist_attr.cc
dist_mapper.cc
dist_tensor.cc)
// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "paddle/phi/core/distributed/auto_parallel/dist_tensor.h"
namespace phi {
namespace distributed {
namespace auto_parallel {
void* DistTensor::AllocateFrom(Allocator* allocator,
DataType dtype,
size_t requested_size,
bool fake_alloc) {
return value_->AllocateFrom(allocator, dtype, requested_size, fake_alloc);
}
const Place& DistTensor::place() const {
PADDLE_ENFORCE_NOT_NULL(
value_->holder_,
phi::errors::PreconditionNotMet(
"Tensor not initialized yet when DenseTensor::place() is called."));
return value_->holder_->place();
}
int64_t DistTensor::numel() const {
if (meta_.is_scalar) {
return 1;
}
return product(meta_.dims);
}
void DistTensor::set_meta(DenseTensorMeta&& meta) {
PADDLE_ENFORCE_EQ(meta_.valid(),
false,
phi::errors::InvalidArgument(
"Only when the original attribute of Tensor is "
"incomplete, can it be reset."));
meta_ = std::move(meta);
}
void DistTensor::set_meta(const DenseTensorMeta& meta) {
PADDLE_ENFORCE_EQ(
meta.valid(),
true,
phi::errors::InvalidArgument(
"Input meta is invalid, please check the meta attribute."));
meta_.dims = meta.dims;
meta_.dtype = meta.dtype;
meta_.is_scalar = meta.is_scalar;
meta_.layout = meta.layout;
meta_.lod = meta.lod;
meta_.offset = meta.offset;
meta_.use_gpudnn = meta.use_gpudnn;
}
} // namespace auto_parallel
} // namespace distributed
} // namespace phi
// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include <memory>
#include "paddle/phi/core/dense_tensor.h"
namespace phi {
namespace distributed {
namespace auto_parallel {
class TensorDistAttr;
class DistTensor final
: public phi::TensorBase,
public phi::TypeInfoTraits<phi::TensorBase, DistTensor> {
public:
/// \brief Construct a dist tensor and allocate space.
/// \param a The allocator used to allocate space.
/// \param meta The meta data of dense tensor.
DistTensor(Allocator* a,
const DenseTensorMeta& meta,
const std::shared_ptr<TensorDistAttr>& dist_attr)
: meta_(meta), dist_attr_(dist_attr) {
value_ = std::make_unique<DenseTensor>(a, meta);
}
DistTensor(Allocator* a,
DenseTensorMeta&& meta,
const std::shared_ptr<TensorDistAttr>& dist_attr)
: meta_(std::move(meta)), dist_attr_(dist_attr) {
value_ = std::make_unique<DenseTensor>(a, meta);
}
DistTensor(const std::shared_ptr<phi::Allocation>& holder,
const DenseTensorMeta& meta,
const std::shared_ptr<TensorDistAttr>& dist_attr)
: meta_(meta), dist_attr_(dist_attr) {
value_ = std::make_unique<DenseTensor>(holder, meta);
}
DistTensor(const std::shared_ptr<phi::DenseTensor>& dense_tensor,
const std::shared_ptr<TensorDistAttr>& dist_attr)
: dist_attr_(dist_attr) {
value_ = std::make_unique<DenseTensor>(*dense_tensor);
set_meta(dense_tensor->meta());
}
~DistTensor() = default;
static const char* name() { return "DistTensor"; }
const DenseTensor& value() const { return *value_; }
DenseTensor* mutable_value() { return value_.get(); }
const std::shared_ptr<TensorDistAttr>& dist_attr() const {
return dist_attr_;
}
/// \brief Returns the number of elements contained in tensor.
/// \return The number of elements contained in tensor.
int64_t numel() const override;
/// \brief Returns the dims of the tensor.
/// \return The dims of the tensor.
const DDim& dims() const override { return meta_.dims; }
/// \brief Test whether the storage is allocated.
/// \return Whether the storage is allocated.
bool initialized() const override {
return value_->holder_ && value_->holder_->ptr();
}
bool IsInitialized() const { return value_->holder_ != nullptr; }
/// \brief Test whether the metadata is valid.
/// \return Whether the metadata is valid.
bool valid() const override { return meta_.valid(); }
/// \brief Allocate memory with requested size from allocator.
/// \return The mutable data pointer value of type T.
void* AllocateFrom(Allocator* allocator,
DataType dtype,
size_t requested_size = 0,
bool fake_alloc = false) override;
/// \brief Returns the data type of the tensor.
/// \return The data type of the tensor.
DataType dtype() const override { return meta_.dtype; }
/// \brief Returns the data layout of the tensor.
/// \return The data layout of the tensor.
DataLayout layout() const override { return meta_.layout; }
/// \brief Returns the data place of the tensor.
/// \return The data place of the tensor.
const Place& place() const override;
const DenseTensorMeta& meta() const noexcept { return meta_; }
/// \brief Sets the meta information of the tensor. Only when the original
/// attribute of Tensor is incomplete, can it be reset.
/// \param meta The meta information of the tensor.
void set_meta(DenseTensorMeta&& meta);
void set_meta(const DenseTensorMeta& meta);
private:
DenseTensorMeta meta_;
std::shared_ptr<TensorDistAttr> dist_attr_{nullptr};
std::unique_ptr<DenseTensor> value_{nullptr};
};
} // namespace auto_parallel
} // namespace distributed
} // namespace phi
...@@ -24,6 +24,9 @@ limitations under the License. */ ...@@ -24,6 +24,9 @@ limitations under the License. */
#include "paddle/phi/core/storage_properties.h" #include "paddle/phi/core/storage_properties.h"
#include "paddle/phi/core/string_tensor.h" #include "paddle/phi/core/string_tensor.h"
#include "paddle/phi/core/tensor_array.h" #include "paddle/phi/core/tensor_array.h"
#ifdef PADDLE_WITH_DISTRIBUTE
#include "paddle/phi/core/distributed/auto_parallel/dist_tensor.h"
#endif
#include "paddle/phi/core/utils/type_info.h" #include "paddle/phi/core/utils/type_info.h"
namespace phi { namespace phi {
...@@ -52,6 +55,11 @@ template class TypeInfoTraits<phi::TensorBase, TensorArray>; ...@@ -52,6 +55,11 @@ template class TypeInfoTraits<phi::TensorBase, TensorArray>;
template class TypeInfoTraits<phi::DeviceContext, CPUContext>; template class TypeInfoTraits<phi::DeviceContext, CPUContext>;
template class TypeInfoTraits<phi::DeviceContext, CustomContext>; template class TypeInfoTraits<phi::DeviceContext, CustomContext>;
#ifdef PADDLE_WITH_DISTRIBUTE
template class TypeInfoTraits<phi::TensorBase,
phi::distributed::auto_parallel::DistTensor>;
#endif
#if defined(PADDLE_WITH_CUDA) || defined(PADDLE_WITH_HIP) || \ #if defined(PADDLE_WITH_CUDA) || defined(PADDLE_WITH_HIP) || \
defined(PADDLE_WITH_XPU_KP) defined(PADDLE_WITH_XPU_KP)
template class TypeInfoTraits<phi::DeviceContext, GPUContext>; template class TypeInfoTraits<phi::DeviceContext, GPUContext>;
......
...@@ -362,6 +362,27 @@ def sparse_tensor_to_string(tensor, prefix='Tensor'): ...@@ -362,6 +362,27 @@ def sparse_tensor_to_string(tensor, prefix='Tensor'):
) )
def dist_tensor_to_string(tensor, prefix='Tensor'):
# TODO(dev): Complete tensor will be printed after reshard
# is ready.
indent = len(prefix) + 1
dtype = convert_dtype(tensor.dtype)
if tensor.dtype == core.VarDesc.VarType.BF16:
dtype = 'bfloat16'
_template = "{prefix}(shape={shape}, dtype={dtype}, place={place}, stop_gradient={stop_gradient}, dist_attr={dist_attr},\n{indent}{data})"
return _template.format(
prefix=prefix,
shape=tensor.shape,
dtype=dtype,
place=tensor._place_str,
stop_gradient=tensor.stop_gradient,
dist_attr=tensor.dist_attr,
indent=' ' * indent,
data=None,
)
def tensor_to_string(tensor, prefix='Tensor'): def tensor_to_string(tensor, prefix='Tensor'):
indent = len(prefix) + 1 indent = len(prefix) + 1
...@@ -374,6 +395,9 @@ def tensor_to_string(tensor, prefix='Tensor'): ...@@ -374,6 +395,9 @@ def tensor_to_string(tensor, prefix='Tensor'):
if tensor.is_sparse(): if tensor.is_sparse():
return sparse_tensor_to_string(tensor, prefix) return sparse_tensor_to_string(tensor, prefix)
if tensor.is_dist():
return dist_tensor_to_string(tensor, prefix)
if not tensor._is_dense_tensor_hold_allocation(): if not tensor._is_dense_tensor_hold_allocation():
return "Tensor(Not initialized)" return "Tensor(Not initialized)"
else: else:
......
...@@ -142,6 +142,7 @@ if(WITH_DISTRIBUTE AND WITH_GPU) ...@@ -142,6 +142,7 @@ if(WITH_DISTRIBUTE AND WITH_GPU)
py_test_modules(test_dist_saver MODULES test_dist_saver) py_test_modules(test_dist_saver MODULES test_dist_saver)
py_test_modules(test_engine_save_load MODULES test_engine_save_load) py_test_modules(test_engine_save_load MODULES test_engine_save_load)
py_test_modules(test_rule_based_tuner MODULES test_rule_based_tuner) py_test_modules(test_rule_based_tuner MODULES test_rule_based_tuner)
py_test_modules(test_dist_tensor MODULES test_dist_tensor)
# End of unittests WITH single card WITHOUT timeout # End of unittests WITH single card WITHOUT timeout
endif() endif()
# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import unittest
import numpy as np
import paddle
class TestDistTensor(unittest.TestCase):
def test_dist_tensor_creation(self):
shape = [10, 5]
dist_attr = paddle.fluid.core.TensorDistAttr()
# create dist tensor using numpy
dist_tensor_with_numpy = paddle.Tensor(
np.ones(shape, dtype=np.float32), dist_attr=dist_attr
)
# create dist tensor using tensor
dist_tensor_with_tensor = paddle.Tensor(
paddle.ones(shape), dist_attr=dist_attr
)
# create normal tensor
tensor = paddle.ones(shape)
# test dist tensor properties
self.assertEqual(dist_tensor_with_numpy.shape, shape)
self.assertEqual(dist_tensor_with_tensor.shape, shape)
self.assertEqual(dist_tensor_with_numpy.is_dist(), True)
self.assertEqual(dist_tensor_with_tensor.is_dist(), True)
self.assertEqual(tensor.is_dist(), False)
self.assertEqual(
str(dist_tensor_with_numpy), str(dist_tensor_with_tensor)
)
self.assertEqual(dist_tensor_with_numpy.dist_attr, dist_attr)
self.assertEqual(dist_tensor_with_tensor.dist_attr, dist_attr)
if __name__ == "__main__":
unittest.main()
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册