Browse Source

Add MatrixInverse (by eigen) CPU op and testcase.

tags/v1.6.0
hezhenhao1 4 years ago
parent
commit
c3194ed4ab
5 changed files with 184 additions and 1 deletions
  1. +1
    -0
      mindspore/ccsrc/backend/kernel_compiler/cpu/cpu_kernel.h
  2. +73
    -0
      mindspore/ccsrc/backend/kernel_compiler/cpu/eigen/matrix_inverse_cpu_kernel.cc
  3. +49
    -0
      mindspore/ccsrc/backend/kernel_compiler/cpu/eigen/matrix_inverse_cpu_kernel.h
  4. +1
    -1
      mindspore/ops/operations/math_ops.py
  5. +60
    -0
      tests/st/ops/cpu/test_matrix_inverse_op.py

+ 1
- 0
mindspore/ccsrc/backend/kernel_compiler/cpu/cpu_kernel.h View File

@@ -100,6 +100,7 @@ constexpr char TRANS[] = "trans";
constexpr char MODE[] = "mode";
constexpr char UNIT_DIAGONAL[] = "unit_diagonal";
constexpr char C_EIEH_VECTOR[] = "compute_eigenvectors";
constexpr char ADJOINT[] = "adjoint";

struct ParallelSearchInfo {
double min_cost_time{DBL_MAX};


+ 73
- 0
mindspore/ccsrc/backend/kernel_compiler/cpu/eigen/matrix_inverse_cpu_kernel.cc View File

@@ -0,0 +1,73 @@
/**
* Copyright 2021 Huawei Technologies Co., Ltd
*
* 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 "backend/kernel_compiler/cpu/eigen/matrix_inverse_cpu_kernel.h"
#include "backend/kernel_compiler/cpu/eigen/eigen_common_utils.h"
#include "Eigen/Dense"
#define EIGEN_NO_MALLOC

namespace mindspore {
namespace kernel {
namespace {
constexpr size_t kMatrixInverseInputsNum = 1;
constexpr size_t kMatrixInverseOutputsNum = 1;
constexpr size_t kMatrixInverseInIndex = 0;
constexpr size_t kMatrixInverseOutIndex = 0;
} // namespace

template <typename T>
void MatrixInverseCPUKernel<T>::InitKernel(const CNodePtr &kernel_node) {
MS_EXCEPTION_IF_NULL(kernel_node);
kernel_name_ = AnfAlgo::GetCNodeName(kernel_node);
size_t input_num = AnfAlgo::GetInputTensorNum(kernel_node);
CHECK_KERNEL_INPUTS_NUM(input_num, kMatrixInverseInputsNum, kernel_name_);
size_t output_num = AnfAlgo::GetOutputTensorNum(kernel_node);
CHECK_KERNEL_OUTPUTS_NUM(output_num, kMatrixInverseOutputsNum, kernel_name_);
auto input_shape = AnfAlgo::GetPrevNodeOutputInferShape(kernel_node, kMatrixInverseInIndex);
if (input_shape.size() < 2) {
MS_LOG(EXCEPTION) << "The dim entered needs to be greater than 2, but " << input_shape.size() << " was taken";
}
size_t last_index = input_shape.size() - 1;
if (input_shape[last_index] != input_shape[last_index - 1]) {
MS_LOG(EXCEPTION) << "The last two dimensions of the input matrix should be equal!";
}
size_ = input_shape[last_index];
for (size_t i = 0; i < last_index - 1; i++) {
batch_size_ *= input_shape[i];
}
adjoint_ = AnfAlgo::GetNodeAttr<bool>(kernel_node, ADJOINT);
}

template <typename T>
bool MatrixInverseCPUKernel<T>::Launch(const std::vector<kernel::AddressPtr> &inputs,
const std::vector<kernel::AddressPtr> &,
const std::vector<kernel::AddressPtr> &outputs) {
auto input_addr = reinterpret_cast<T *>(inputs[kMatrixInverseInIndex]->addr);
auto output_addr = reinterpret_cast<T *>(outputs[kMatrixInverseOutIndex]->addr);

for (size_t i = 0; i < batch_size_; i++) {
size_t offset = i * size_ * size_;
Map<Matrix<T, RowMajor>> input(input_addr + offset, size_, size_);
Map<Matrix<T, RowMajor>> output(output_addr + offset, size_, size_);
output = input.inverse();
if (output.RowsAtCompileTime == 0 || output.ColsAtCompileTime == 0) {
MS_LOG_EXCEPTION << kernel_name_ << " output shape is invalid.";
}
}
return true;
}
} // namespace kernel
} // namespace mindspore

+ 49
- 0
mindspore/ccsrc/backend/kernel_compiler/cpu/eigen/matrix_inverse_cpu_kernel.h View File

@@ -0,0 +1,49 @@
/**
* Copyright 2021 Huawei Technologies Co., Ltd
*
* 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.
*/

#ifndef MINDSPORE_MATRIX_INVERSE_CPU_KERNEL_H
#define MINDSPORE_MATRIX_INVERSE_CPU_KERNEL_H

#include <vector>
#include "backend/kernel_compiler/cpu/cpu_kernel.h"
#include "backend/kernel_compiler/cpu/cpu_kernel_factory.h"

namespace mindspore {
namespace kernel {
template <typename T>
class MatrixInverseCPUKernel : public CPUKernel {
public:
MatrixInverseCPUKernel() = default;
~MatrixInverseCPUKernel() override = default;

void InitKernel(const CNodePtr &kernel_node) override;
bool Launch(const std::vector<AddressPtr> &inputs, const std::vector<AddressPtr> &workspace,
const std::vector<AddressPtr> &outputs) override;

private:
size_t batch_size_{1};
size_t size_{1};
bool adjoint_{false};
};

MS_REG_CPU_KERNEL_T(MatrixInverse, KernelAttr().AddInputAttr(kNumberTypeFloat32).AddOutputAttr(kNumberTypeFloat32),
MatrixInverseCPUKernel, float);
MS_REG_CPU_KERNEL_T(MatrixInverse, KernelAttr().AddInputAttr(kNumberTypeFloat64).AddOutputAttr(kNumberTypeFloat64),
MatrixInverseCPUKernel, double);
} // namespace kernel
} // namespace mindspore

#endif // MINDSPORE_MATRIX_INVERSE_CPU_KERNEL_H

+ 1
- 1
mindspore/ops/operations/math_ops.py View File

@@ -5252,7 +5252,7 @@ class MatrixInverse(PrimitiveWithInfer):
ValueError: If the dimension of `x` is less than 2.

Supported Platforms:
``GPU``
``GPU`` ``CPU``

Examples:
>>> x = Tensor(np.array([[[-0.710504 , -1.1207525],


+ 60
- 0
tests/st/ops/cpu/test_matrix_inverse_op.py View File

@@ -0,0 +1,60 @@
# Copyright 2019 Huawei Technologies Co., Ltd
#
# 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 matrix_inverseress or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ============================================================================

import numpy as np
from numpy.linalg import inv
import pytest

import mindspore.context as context
import mindspore.nn as nn
from mindspore import Tensor
from mindspore.ops import operations as P

np.random.seed(1)

class NetMatrixInverse(nn.Cell):
def __init__(self):
super(NetMatrixInverse, self).__init__()
self.matrix_inverse = P.MatrixInverse()

def construct(self, x):
return self.matrix_inverse(x)


@pytest.mark.level0
@pytest.mark.platform_x86_gpu_training
@pytest.mark.env_onecard
@pytest.mark.parametrize('dtype', [np.float32, np.float64])
def test_matrix_inverse(dtype):
"""
Feature: ALL To ALL
Description: test cases for MatrixInverse
Expectation: the result match to numpy
"""
x0_np = np.random.uniform(-2, 2, (3, 4, 4)).astype(dtype)
x0 = Tensor(x0_np)
expect0 = inv(x0_np)

context.set_context(mode=context.GRAPH_MODE, device_target="CPU")
matrix_inverse = NetMatrixInverse()
output0 = matrix_inverse(x0).asnumpy()
np.testing.assert_almost_equal(expect0, output0, decimal=5)
assert output0.shape == expect0.shape

context.set_context(mode=context.PYNATIVE_MODE, device_target="CPU")
matrix_inverse = NetMatrixInverse()
output0 = matrix_inverse(x0).asnumpy()
np.testing.assert_almost_equal(expect0, output0, decimal=5)
assert output0.shape == expect0.shape

Loading…
Cancel
Save