forked from mindspore-Ecosystem/mindspore
!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:
commit
f0714345d6
|
@ -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]) - float,complex或bool类型的Tensor。
|
||||
- **y** (Union[Tensor, Number, bool]) - float、complex或bool类型的Tensor。`x` 和 `y` 不能同时为bool类型。
|
||||
|
||||
返回:
|
||||
Tensor,shape与广播后的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是不支持数据类型转换。
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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}},
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue