未验证 提交 bca30316 编写于 作者: S ShenLiang 提交者: GitHub

fix inverse bug (#25641)

* fix inverse bug, test=develop

* fix the untest, test=develop

* add singular checking, test=develop

* fix the utest, test=develop

* use memory::copy, test=develop

* fix bost_get, test=develop

* fix position, test=develop
上级 a07b6262
...@@ -67,6 +67,8 @@ class MatrixInverseFunctor<platform::CUDADeviceContext, T> { ...@@ -67,6 +67,8 @@ class MatrixInverseFunctor<platform::CUDADeviceContext, T> {
auto blas = math::GetBlas<platform::CUDADeviceContext, T>(context); auto blas = math::GetBlas<platform::CUDADeviceContext, T>(context);
std::vector<int> info; // only for singular checking
info.resize(batch_size);
// This functions in cuBLAS is intended to be used for matrices of small // This functions in cuBLAS is intended to be used for matrices of small
// sizes where the launch overhead is a significant factor. // sizes where the launch overhead is a significant factor.
// TODO(Xreki): call function in cusolver for large matrices. // TODO(Xreki): call function in cusolver for large matrices.
...@@ -91,6 +93,15 @@ class MatrixInverseFunctor<platform::CUDADeviceContext, T> { ...@@ -91,6 +93,15 @@ class MatrixInverseFunctor<platform::CUDADeviceContext, T> {
reinterpret_cast<const T**>(tmp_gpu_ptrs_data->ptr()), reinterpret_cast<const T**>(tmp_gpu_ptrs_data->ptr()),
gpu_pivot_ptr, gpu_inv_ptrs, gpu_info_ptr, batch_size); gpu_pivot_ptr, gpu_inv_ptrs, gpu_info_ptr, batch_size);
} }
memory::Copy(platform::CPUPlace(), info.data(),
BOOST_GET_CONST(platform::CUDAPlace, context.GetPlace()),
gpu_info_ptr, sizeof(int) * batch_size, context.stream());
for (int i = 0; i < batch_size; ++i) {
PADDLE_ENFORCE_EQ(info[i], 0,
platform::errors::PreconditionNotMet(
"For batch [%d]: U(%d, %d) is zero, singular U.", i,
info[i], info[i]));
}
} }
}; };
......
...@@ -140,5 +140,47 @@ class TestInverseAPIError(unittest.TestCase): ...@@ -140,5 +140,47 @@ class TestInverseAPIError(unittest.TestCase):
self.assertRaises(ValueError, paddle.inverse, input) self.assertRaises(ValueError, paddle.inverse, input)
class TestInverseSingularAPI(unittest.TestCase):
def setUp(self):
self.places = [fluid.CPUPlace()]
if core.is_compiled_with_cuda():
self.places.append(fluid.CUDAPlace(0))
def check_static_result(self, place, with_out=False):
with fluid.program_guard(fluid.Program(), fluid.Program()):
input = fluid.data(name="input", shape=[4, 4], dtype="float64")
if with_out:
out = fluid.data(name="output", shape=[4, 4], dtype="float64")
else:
out = None
result = paddle.inverse(input=input, out=out)
input_np = np.zeros([4, 4]).astype("float64")
exe = fluid.Executor(place)
try:
fetches = exe.run(fluid.default_main_program(),
feed={"input": input_np},
fetch_list=[result])
except fluid.core.EnforceNotMet as ex:
print("The mat is singular")
pass
def test_static(self):
for place in self.places:
self.check_static_result(place=place)
def test_dygraph(self):
for place in self.places:
with fluid.dygraph.guard(place):
input_np = np.ones([4, 4]).astype("float64")
input = fluid.dygraph.to_variable(input_np)
try:
result = paddle.inverse(input)
except fluid.core.EnforceNotMet as ex:
print("The mat is singular")
pass
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.
先完成此消息的编辑!
想要评论请 注册