!49838 multinomial op support 1d input

Merge pull request !49838 from xulei/multinomial
This commit is contained in:
i-robot 2023-03-08 06:08:31 +00:00 committed by Gitee
commit 7d1eb8b6c1
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
4 changed files with 15 additions and 24 deletions

View File

@ -14,7 +14,7 @@ mindspore.ops.Multinomial
- **dtype** (dtype) - 输出数据类型必须是int32或者int64默认类型int32。 - **dtype** (dtype) - 输出数据类型必须是int32或者int64默认类型int32。
输入: 输入:
- **x** (Tensor) - 包含累加概率和的输入Tensor必须是一维或二维。CPU和GPU后端支持一维或者二维Ascend后端仅支持二维。 - **x** (Tensor) - 包含累加概率和的输入Tensor必须是一维或二维。
- **num_samples** (int) - 要抽取的样本数。 - **num_samples** (int) - 要抽取的样本数。
输出: 输出:

View File

@ -33,6 +33,8 @@ using namespace std;
namespace { namespace {
const char *kMultinomial = "Multinomial"; const char *kMultinomial = "Multinomial";
const auto kRankOne = 1;
const auto kRankTwo = 2;
const uint32_t kOutputNum = 1; const uint32_t kOutputNum = 1;
const uint32_t kInputNum = 2; const uint32_t kInputNum = 2;
constexpr int64_t kParallelDataNums = 40 * 1024; constexpr int64_t kParallelDataNums = 40 * 1024;
@ -41,16 +43,16 @@ using RNG_Engine = std::mt19937;
// override isfinite for half // override isfinite for half
bool isfinite(Eigen::half &data) { return Eigen::half_impl::isfinite(data); } bool isfinite(Eigen::half &data) { return Eigen::half_impl::isfinite(data); }
} // namespace } // namespace
namespace aicpu { namespace aicpu {
template <typename T_in, typename T_out> template <typename T_in, typename T_out>
uint32_t Generate(Tensor *&input_0, Tensor *&input_1, Tensor *&input_count, Tensor *&input_state, Tensor *&output, uint32_t Generate(Tensor *&input_0, Tensor *&input_1, Tensor *&input_count, Tensor *&input_state, Tensor *&output,
CpuKernelContext &ctx) { CpuKernelContext &ctx) {
int64_t num_classes = input_0->GetTensorShape()->GetDimSize(1); const auto &input_shape = input_0->GetTensorShape();
int64_t batch_size = input_0->GetTensorShape()->GetDimSize(0); const auto input_rank = input_shape->GetDims();
int64_t batch_size = input_rank == 1 ? 1 : input_shape->GetDimSize(0);
int64_t num_classes = input_shape->GetDimSize(input_rank - 1);
int32_t num_samples = *(reinterpret_cast<int32_t *>(input_1->GetData())); int32_t num_samples = *(reinterpret_cast<int32_t *>(input_1->GetData()));
// count the execution times of the op // count the execution times of the op
uint64_t count = *(reinterpret_cast<uint64_t *>(input_count->GetData())); uint64_t count = *(reinterpret_cast<uint64_t *>(input_count->GetData()));
@ -85,7 +87,6 @@ uint32_t Generate(Tensor *&input_0, Tensor *&input_1, Tensor *&input_count, Tens
auto input_0_data = reinterpret_cast<T_in *>(input_0->GetData()); auto input_0_data = reinterpret_cast<T_in *>(input_0->GetData());
auto output_data = reinterpret_cast<T_out *>(output->GetData()); auto output_data = reinterpret_cast<T_out *>(output->GetData());
auto total_num = output->NumElements(); auto total_num = output->NumElements();
if (total_num < kParallelDataNums) { if (total_num < kParallelDataNums) {
auto cur_out = output_data; auto cur_out = output_data;
@ -198,15 +199,16 @@ uint32_t MultinomialCpuKernel::Compute(CpuKernelContext &ctx) {
"Input[1] data type must DT_INT32, but got data type[%s].", DTypeStr(input1_datatype).c_str()); "Input[1] data type must DT_INT32, but got data type[%s].", DTypeStr(input1_datatype).c_str());
// check input dimension // check input dimension
KERNEL_CHECK_FALSE((input_0->GetTensorShape()->GetDims() == 2), KERNEL_STATUS_PARAM_INVALID, const auto rank_0 = input_0->GetTensorShape()->GetDims();
"Input[0] should be a matrix, but got rank [%d].", input_0->GetTensorShape()->GetDims()); KERNEL_CHECK_FALSE((rank_0 == kRankOne || rank_0 == kRankTwo), KERNEL_STATUS_PARAM_INVALID,
"Rank of input[0] should be 1 or 2, but got rank [%d].", input_0->GetTensorShape()->GetDims());
// scalar input is converted to rank-zero tensor in the dynamic input scenario. // scalar input is converted to rank-zero tensor in the dynamic input scenario.
// rank-zero tensor from ms has a dim of 1, so limit input1 dim so that it's smaller than 1. // rank-zero tensor from ms has a dim of 1, so limit input1 dim so that it's smaller than 1.
KERNEL_CHECK_FALSE((input_1->GetTensorShape()->GetDims() <= 1), KERNEL_STATUS_PARAM_INVALID, KERNEL_CHECK_FALSE((input_1->GetTensorShape()->GetDims() <= 1), KERNEL_STATUS_PARAM_INVALID,
"Input[1] should be a scalar, but got rank [%d].", input_1->GetTensorShape()->GetDims()); "Input[1] should be a scalar, but got rank [%d].", input_1->GetTensorShape()->GetDims());
// check num_classes positive // check num_classes positive
auto num_classes = input_0->GetTensorShape()->GetDimSize(1); // int64_t auto num_classes = input_0->GetTensorShape()->GetDimSize(rank_0 - 1); // int64_t
KERNEL_CHECK_FALSE((num_classes > 0), KERNEL_STATUS_PARAM_INVALID, "num_classes should be positive, but got [%d].", KERNEL_CHECK_FALSE((num_classes > 0), KERNEL_STATUS_PARAM_INVALID, "num_classes should be positive, but got [%d].",
num_classes); num_classes);

View File

@ -58,20 +58,9 @@ abstract::ShapePtr MultinomialInferShape(const PrimitivePtr &primitive,
} }
const int64_t x_rank_max = 2; const int64_t x_rank_max = 2;
const int64_t x_rank_min = 1; const int64_t x_rank_min = 1;
auto context_ptr = MsContext::GetInstance(); if (x_shape.size() > x_rank_max || x_shape.size() < x_rank_min) {
MS_EXCEPTION_IF_NULL(context_ptr); MS_EXCEPTION(ValueError) << "For '" << primitive->name() << "', input[x] dimension must be 1 or 2, but got rank "
auto is_ascend = (context_ptr->get_param<std::string>(MS_CTX_DEVICE_TARGET) == kAscendDevice); << x_shape.size() << ".";
if (is_ascend) {
if (x_shape.size() != x_rank_max) {
MS_EXCEPTION(ValueError) << "For '" << primitive->name()
<< "', input[x] dimension must be 2 in Ascend, but got rank " << x_shape.size() << ".";
}
} else {
if (x_shape.size() > x_rank_max || x_shape.size() < x_rank_min) {
MS_EXCEPTION(ValueError) << "For '" << primitive->name()
<< "', input[x] dimension must be 1 or 2 in CPU and GPU, but got rank " << x_shape.size()
<< ".";
}
} }
int64_t num_samples_val = 0; int64_t num_samples_val = 0;

View File

@ -797,7 +797,7 @@ class Multinomial(Primitive):
Inputs: Inputs:
- **x** (Tensor) - the input tensor containing the cumsum of probabilities, must be 1 or 2 - **x** (Tensor) - the input tensor containing the cumsum of probabilities, must be 1 or 2
dimensions. CPU and GPU supports x 1 or 2 dimensions and Ascend only supports 2 dimensions. dimensions.
- **num_samples** (int) - number of samples to draw, must be a nonnegative number. - **num_samples** (int) - number of samples to draw, must be a nonnegative number.
Outputs: Outputs: