未验证 提交 5c5a2a83 编写于 作者: W Weilong Wu 提交者: GitHub

[Eager] Support SelectedRows in eager mode (#40858)

* [Eager] Support SelectedRows in eager mode

* Remove unnecessary codes

* Adapt new dygraph flag
上级 34f07045
...@@ -193,23 +193,53 @@ static PyObject* tensor_method_numpy(TensorObject* self, PyObject* args, ...@@ -193,23 +193,53 @@ static PyObject* tensor_method_numpy(TensorObject* self, PyObject* args,
} }
if (self->tensor.is_cpu() || self->tensor.is_gpu_pinned()) { if (self->tensor.is_cpu() || self->tensor.is_gpu_pinned()) {
platform::CPUPlace place;
if (self->tensor.is_selected_rows()) {
VLOG(6) << "Getting SelectedRows's numpy value";
auto* selected_rows =
static_cast<phi::SelectedRows*>(self->tensor.impl().get());
auto* dense_tensor = static_cast<paddle::framework::LoDTensor*>(
selected_rows->mutable_value());
// deep copy
paddle::memory::Copy(
place,
reinterpret_cast<void*>(pybind11::detail::array_proxy(array)->data),
place, dense_tensor->data(), sizeof_dtype * numel);
} else {
VLOG(6) << "Getting DenseTensor's numpy value";
auto dense_tensor = auto dense_tensor =
std::dynamic_pointer_cast<phi::DenseTensor>(self->tensor.impl()); std::dynamic_pointer_cast<phi::DenseTensor>(self->tensor.impl());
platform::CPUPlace place;
// deep copy // deep copy
paddle::memory::Copy(place, reinterpret_cast<void*>( paddle::memory::Copy(
pybind11::detail::array_proxy(array)->data), place,
reinterpret_cast<void*>(pybind11::detail::array_proxy(array)->data),
place, dense_tensor->data(), sizeof_dtype * numel); place, dense_tensor->data(), sizeof_dtype * numel);
}
#if defined(PADDLE_WITH_CUDA) #if defined(PADDLE_WITH_CUDA)
} else if (self->tensor.is_gpu()) { } else if (self->tensor.is_gpu()) {
if (self->tensor.is_selected_rows()) {
VLOG(6) << "Getting SelectedRows's numpy value";
auto* selected_rows =
static_cast<phi::SelectedRows*>(self->tensor.impl().get());
auto* dense_tensor = static_cast<paddle::framework::LoDTensor*>(
selected_rows->mutable_value());
paddle::platform::GpuMemcpySync(
pybind11::detail::array_proxy(array)->data, dense_tensor->data(),
paddle::framework::DataTypeSize(dense_tensor->dtype()) *
dense_tensor->numel(),
cudaMemcpyDeviceToHost);
} else {
VLOG(6) << "Getting DenseTensor's numpy value";
auto dense_tensor = auto dense_tensor =
std::dynamic_pointer_cast<phi::DenseTensor>(self->tensor.impl()); std::dynamic_pointer_cast<phi::DenseTensor>(self->tensor.impl());
paddle::platform::GpuMemcpySync( paddle::platform::GpuMemcpySync(
pybind11::detail::array_proxy(array)->data, dense_tensor->data(), pybind11::detail::array_proxy(array)->data, dense_tensor->data(),
paddle::framework::DataTypeSize(dense_tensor->dtype()) * paddle::framework::DataTypeSize(dense_tensor->dtype()) *
dense_tensor->numel(), dense_tensor->numel(),
cudaMemcpyDeviceToHost); cudaMemcpyDeviceToHost);
}
#endif #endif
} else { } else {
PADDLE_THROW(platform::errors::InvalidArgument( PADDLE_THROW(platform::errors::InvalidArgument(
...@@ -1149,6 +1179,26 @@ static PyObject* tensor__inplace_version(TensorObject* self, PyObject* args, ...@@ -1149,6 +1179,26 @@ static PyObject* tensor__inplace_version(TensorObject* self, PyObject* args,
EAGER_CATCH_AND_THROW_RETURN_NULL EAGER_CATCH_AND_THROW_RETURN_NULL
} }
static PyObject* tensor_method_is_selected_rows(TensorObject* self,
PyObject* args,
PyObject* kwargs) {
EAGER_TRY
return ToPyObject(self->tensor.is_selected_rows());
EAGER_CATCH_AND_THROW_RETURN_NULL
}
static PyObject* tensor_method_get_rows(TensorObject* self, PyObject* args,
PyObject* kwargs) {
EAGER_TRY
PADDLE_ENFORCE(self->tensor.is_selected_rows(),
paddle::platform::errors::Fatal(
"this method is only effective for SelectedRows"));
auto selected_rows =
std::dynamic_pointer_cast<phi::SelectedRows>(self->tensor.impl());
return ToPyObject(selected_rows->rows());
EAGER_CATCH_AND_THROW_RETURN_NULL
}
PyMethodDef variable_methods[] = { PyMethodDef variable_methods[] = {
{"numpy", (PyCFunction)(void (*)(void))tensor_method_numpy, {"numpy", (PyCFunction)(void (*)(void))tensor_method_numpy,
METH_VARARGS | METH_KEYWORDS, NULL}, METH_VARARGS | METH_KEYWORDS, NULL},
...@@ -1237,6 +1287,11 @@ PyMethodDef variable_methods[] = { ...@@ -1237,6 +1287,11 @@ PyMethodDef variable_methods[] = {
/***the method of sparse tensor****/ /***the method of sparse tensor****/
{"_inplace_version", (PyCFunction)(void (*)(void))tensor__inplace_version, {"_inplace_version", (PyCFunction)(void (*)(void))tensor__inplace_version,
METH_VARARGS | METH_KEYWORDS, NULL}, METH_VARARGS | METH_KEYWORDS, NULL},
{"is_selected_rows",
(PyCFunction)(void (*)(void))tensor_method_is_selected_rows,
METH_VARARGS | METH_KEYWORDS, NULL},
{"rows", (PyCFunction)(void (*)(void))tensor_method_get_rows,
METH_VARARGS | METH_KEYWORDS, NULL},
{NULL, NULL, 0, NULL}}; {NULL, NULL, 0, NULL}};
} // namespace pybind } // namespace pybind
......
...@@ -26,7 +26,7 @@ from . import core ...@@ -26,7 +26,7 @@ from . import core
from . import name_scope from . import name_scope
from .dygraph import base as imperative_base from .dygraph import base as imperative_base
from .data_feeder import check_variable_and_dtype from .data_feeder import check_variable_and_dtype
from .framework import _non_static_mode from .framework import _non_static_mode, in_dygraph_mode, _in_legacy_dygraph
from .layer_helper import LayerHelper from .layer_helper import LayerHelper
from .framework import default_main_program from .framework import default_main_program
from paddle import _C_ops from paddle import _C_ops
...@@ -70,7 +70,13 @@ def _squared_l2_norm(x): ...@@ -70,7 +70,13 @@ def _squared_l2_norm(x):
sum_square = layers.reduce_sum(square) sum_square = layers.reduce_sum(square)
return sum_square return sum_square
if _non_static_mode(): if in_dygraph_mode():
if x.is_selected_rows():
new_x = paddle.to_tensor(x.numpy())
return _C_ops.squared_l2_norm(new_x)
return _C_ops.squared_l2_norm(x)
else:
if _in_legacy_dygraph():
return _C_ops.squared_l2_norm(x) return _C_ops.squared_l2_norm(x)
op_type = 'squared_l2_norm' op_type = 'squared_l2_norm'
......
...@@ -325,7 +325,8 @@ def monkey_patch_varbase(): ...@@ -325,7 +325,8 @@ def monkey_patch_varbase():
if framework._in_eager_mode_: if framework._in_eager_mode_:
if self.grad is None: if self.grad is None:
return None return None
# TODO(wanghuancoder) support SELECTED_ROWS if self.grad.is_selected_rows():
return (np.array(self.grad.numpy()), np.array(self.grad.rows()))
return self.grad.numpy() return self.grad.numpy()
else: else:
if self._grad_ivar() is None: if self._grad_ivar() is None:
......
...@@ -22,6 +22,7 @@ from paddle.fluid.optimizer import SGDOptimizer ...@@ -22,6 +22,7 @@ from paddle.fluid.optimizer import SGDOptimizer
import numpy as np import numpy as np
import paddle.fluid.core as core import paddle.fluid.core as core
import paddle import paddle
from paddle.fluid.framework import _test_eager_guard
class SimpleNet(paddle.nn.Layer): class SimpleNet(paddle.nn.Layer):
...@@ -39,7 +40,7 @@ class SimpleNet(paddle.nn.Layer): ...@@ -39,7 +40,7 @@ class SimpleNet(paddle.nn.Layer):
class TestSimpleNet(unittest.TestCase): class TestSimpleNet(unittest.TestCase):
def test_selectedrows_gradient1(self): def func_selectedrows_gradient1(self):
places = [fluid.CPUPlace()] places = [fluid.CPUPlace()]
if core.is_compiled_with_cuda(): if core.is_compiled_with_cuda():
places.append(fluid.CUDAPlace(0)) places.append(fluid.CUDAPlace(0))
...@@ -77,7 +78,12 @@ class TestSimpleNet(unittest.TestCase): ...@@ -77,7 +78,12 @@ class TestSimpleNet(unittest.TestCase):
self.assertTrue(input_emb.gradient() is not None) self.assertTrue(input_emb.gradient() is not None)
paddle.enable_static() paddle.enable_static()
def test_selectedrows_gradient2(self): def test_selectedrows_gradient1(self):
with _test_eager_guard():
self.func_selectedrows_gradient1()
self.func_selectedrows_gradient1()
def func_selectedrows_gradient2(self):
places = [fluid.CPUPlace()] places = [fluid.CPUPlace()]
if core.is_compiled_with_cuda(): if core.is_compiled_with_cuda():
places.append(fluid.CUDAPlace(0)) places.append(fluid.CUDAPlace(0))
...@@ -113,6 +119,11 @@ class TestSimpleNet(unittest.TestCase): ...@@ -113,6 +119,11 @@ class TestSimpleNet(unittest.TestCase):
input_emb.clear_gradient() input_emb.clear_gradient()
self.assertTrue(input_emb.gradient() is not None) self.assertTrue(input_emb.gradient() is not None)
def test_selectedrows_gradient2(self):
with _test_eager_guard():
self.func_selectedrows_gradient2()
self.func_selectedrows_gradient2()
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册