!39937 Optimize error msg && add function api desc for xdivy & support dynamic rank

Merge pull request !39937 from zhangzhaoju/master
This commit is contained in:
i-robot 2022-08-22 11:25:40 +00:00 committed by Gitee
commit f0714345d6
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
5 changed files with 76 additions and 23 deletions

View File

@ -0,0 +1,21 @@
mindspore.ops.xlogy
====================
.. py:function:: mindspore.ops.xdivy(x, y)
将第一个输入Tensor除以第二个输入Tensor。当 `x` 为零时,则返回零。
`x``y` 的输入遵循隐式类型转换规则使数据类型一致。输入必须是两个Tensor或一个Tensor和一个Scalar。当输入是两个Tensor时它们的数据类型不能同时bool它们的shape可以广播。当输入是一个Tensor和一个Scalar时Scalar只能是一个常量。
参数:
- **x** (Union[Tensor, Number, bool]) - floatcomplex或bool类型的Tensor。
- **y** (Union[Tensor, Number, bool]) - float、complex或bool类型的Tensor。`x``y` 不能同时为bool类型。
返回:
Tensorshape与广播后的shape相同数据类型为两个输入中精度较高或数据类型较高的类型。
异常:
- **TypeError** - 如果 `x``y` 不是以下之一Tensor、Number、bool。
- **TypeError** - 如果 `x``y` 的数据类型不是float16、float32、float64、complex64、complex128、bool。
- **ValueError** - 如果 `x` 不能广播至 `y` 的shape。
- **RuntimeError** - 如果Parameter的 `x` , `y` 需要进行数据类型转换但是Parameter是不支持数据类型转换。

View File

@ -19,12 +19,14 @@
#include <limits>
#include <cmath>
#include "plugin/device/cpu/hal/device/cpu_device_address.h"
#include "Eigen/Eigen"
namespace mindspore {
namespace kernel {
static constexpr size_t INPUT_NUM = 2;
static constexpr size_t OUTPUT_NUM = 1;
static constexpr int MAX_DIMS = 7;
static constexpr size_t PARALLEL_THRESHOLD = 4096;
template <typename T>
T GetDivZeroVal(const T &v) {
auto zero = static_cast<T>(0.0);
@ -32,7 +34,7 @@ T GetDivZeroVal(const T &v) {
}
template <>
complex128 GetDivZeroVal(const complex128 &v) {
complex128 GetDivZeroVal(const complex128 &) {
return std::numeric_limits<complex128>::quiet_NaN();
}
@ -42,20 +44,53 @@ complex64 GetDivZeroVal(const complex64 &) {
}
template <class T>
bool isZero(T val) {
bool isZero(const T &val) {
return val == T(0.0f);
}
template <>
bool isZero(float val) {
bool isZero(const float &val) {
return std::fpclassify(val) == FP_ZERO;
}
template <>
bool isZero(double val) {
bool isZero(const double &val) {
return std::fpclassify(val) == FP_ZERO;
}
template <typename T>
void SameShapeTask(T *x_addr, T *y_addr, T *output_addr, size_t start, size_t end) {
for (size_t i = start; i < end; i++) {
auto dividend = x_addr[i];
auto divisor = y_addr[i];
if (isZero(divisor)) {
if (isZero(dividend)) {
output_addr[i] = static_cast<T>(0.0);
continue;
}
output_addr[i] = GetDivZeroVal(dividend);
continue;
}
output_addr[i] = dividend / divisor;
}
}
template <>
void SameShapeTask(float *x_addr, float *y_addr, float *output_addr, size_t start, size_t end) {
Eigen::Map<Eigen::ArrayXf> x_v(x_addr + start, end - start);
Eigen::Map<Eigen::ArrayXf> y_v(y_addr + start, end - start);
Eigen::Map<Eigen::ArrayXf> o_v(output_addr + start, end - start);
o_v = (x_v == 0).select(o_v, x_v / y_v);
}
template <>
void SameShapeTask(double *x_addr, double *y_addr, double *output_addr, size_t start, size_t end) {
Eigen::Map<Eigen::ArrayXd> x_v(x_addr + start, end - start);
Eigen::Map<Eigen::ArrayXd> y_v(y_addr + start, end - start);
Eigen::Map<Eigen::ArrayXd> o_v(output_addr + start, end - start);
o_v = (x_v == 0).select(o_v, x_v / y_v);
}
template <typename T>
bool XdivyCpuKernelMod::LaunchKernel(const std::vector<kernel::AddressPtr> &inputs,
const std::vector<kernel::AddressPtr> &,
@ -67,19 +102,7 @@ bool XdivyCpuKernelMod::LaunchKernel(const std::vector<kernel::AddressPtr> &inpu
auto output_addr = static_cast<T *>(outputs[0]->addr);
size_t output_size = outputs[0]->size / sizeof(T);
auto sameShapeTask = [&x_addr, &y_addr, &output_addr](size_t start, size_t end) {
for (size_t i = start; i < end; i++) {
auto dividend = x_addr[i];
auto divisor = y_addr[i];
if (isZero(divisor)) {
if (isZero(dividend)) {
output_addr[i] = static_cast<T>(0.0);
continue;
}
output_addr[i] = GetDivZeroVal(dividend);
continue;
}
output_addr[i] = dividend / divisor;
}
SameShapeTask(x_addr, y_addr, output_addr, start, end);
};
auto diffShapeTask = [this, &x_addr, &y_addr, &output_addr](size_t start, size_t end) {
for (size_t i = start; i < end; i++) {
@ -100,10 +123,11 @@ bool XdivyCpuKernelMod::LaunchKernel(const std::vector<kernel::AddressPtr> &inpu
}
};
if (is_need_broadcast_) {
ParallelLaunch(diffShapeTask, output_size, 0, this, pool_);
CTask task = is_need_broadcast_ ? CTask(diffShapeTask) : CTask(sameShapeTask);
if (output_size < PARALLEL_THRESHOLD) {
task(0, output_size);
} else {
ParallelLaunch(sameShapeTask, output_size, 0, this, pool_);
ParallelLaunch(task, output_size, PARALLEL_THRESHOLD, this, pool_);
}
return true;
}

View File

@ -127,9 +127,10 @@ int BroadcastOpGpuKernelMod::Resize(const BaseOperatorPtr &base_operator, const
}
need_broadcast_ = common::AnfAlgo::IsTensorBroadcast(lhs_shape_, rhs_shape_);
if (!broadcast_utils::AlignedBroadCastShape(MAX_DIMS, &output_shape_, &lhs_shape_, &rhs_shape_)) {
MS_LOG(ERROR) << "For '" << kernel_name_ << "', it's dimension of input cannot be greater than " << MAX_DIMS
<< ", but got " << lhs_shape_.size();
return KRET_RESIZE_FAILED;
MS_LOG(EXCEPTION) << "For '" << kernel_name_ << "', the dimension of input cannot be greater than " << MAX_DIMS
<< ", and output dimension can't less than input; but got x_shape dimension:" << lhs_shape_.size()
<< " ,y_shape dimension:" << rhs_shape_.size()
<< " ,out_shape dimension:" << output_shape_.size();
}
return KRET_OK;
}

View File

@ -54,6 +54,7 @@
#include "ops/max_pool.h"
#include "ops/grad/max_pool_grad.h"
#include "ops/dropout.h"
#include "ops/xdivy.h"
namespace mindspore {
namespace abstract {
@ -386,6 +387,7 @@ PrimitiveEvalImplMap &GetPrimitiveToBackendEvalImplMap() {
{prim::kPrimUnsortedSegmentSum, R{InferImplUnsortedSegmentSum, nullptr, true}},
{prim::kPrimDiv, R{InferImplDiv, nullptr, true}},
{prim::kPrimRealDiv, R{ops::RealDivInfer, nullptr, false}},
{prim::kPrimXdivy, R{ops::XdivyInfer, nullptr, true}},
{prim::kPrimTranspose, R{InferImplTranspose, nullptr, true}},
{prim::kPrimTransposeNOD, R{InferImplTranspose, nullptr, true}},
{prim::kPrimStridedSlice, R{ops::StridedSliceInfer, nullptr, true}},

View File

@ -77,6 +77,11 @@ abstract::ShapePtr BroadCastInferShape(const std::string &op_name, const std::ve
auto y_min_shape = y_shape_map[kMinShape];
auto y_max_shape = y_shape_map[kMaxShape];
// ToSupport Dynamic rank
if (IsDynamicRank(x_shape) || IsDynamicRank(y_shape)) {
return std::make_shared<abstract::Shape>(std::vector<int64_t>{-2});
}
if (x_shape == y_shape) {
return std::make_shared<abstract::Shape>(x_shape, x_min_shape, x_max_shape);
}