!33978 [assistant][UpsampleTrilinear3d ][UpsampleTrilinear3dGrad] add new ascend operator UpsampleTrilinear3d & UpsampleTrilinear3dGrad

Merge pull request !33978 from 李文轼/Trilinear3d
This commit is contained in:
i-robot 2022-08-11 08:58:10 +00:00 committed by Gitee
commit b78043c1f6
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
19 changed files with 870 additions and 245 deletions

View File

@ -245,6 +245,51 @@ inline size_t NearestIndex(const size_t &output_index, const size_t &input_size,
}
}
template <typename T>
inline T AreaPixelComputeScale(int64_t input_size, int64_t output_size, bool align_corners, double scale) {
if (align_corners) {
if (output_size > 1) {
return static_cast<T>(input_size - 1) / (output_size - 1);
} else {
return static_cast<T>(0);
}
} else {
return ComputeScales<T>(scale, input_size, output_size);
}
}
template <typename T>
inline T AreaPixelComputeSourceIndex(T scale, int64_t dst_index, bool align_corners) {
if (align_corners) {
return scale * static_cast<T>(dst_index);
} else {
constexpr T zero = 0.;
T src_idx = scale * (dst_index + 0.5) - 0.5;
return src_idx < zero ? zero : src_idx;
}
}
template <typename T>
inline void ComputeSourceIndexAndLambda(int64_t *const input_index0, int64_t *const input_index1, T *const lambda0,
T *const lambda1, T ratio, int64_t output_index, int64_t input_size,
int64_t output_size, bool align_corners) {
if (output_size == input_size) {
// scale_factor = 1
*input_index0 = output_index;
*input_index1 = output_index;
*lambda0 = static_cast<T>(1);
*lambda1 = static_cast<T>(0);
} else {
const T real_input_index = AreaPixelComputeSourceIndex<T>(ratio, output_index, align_corners);
*input_index0 = static_cast<int64_t>(real_input_index);
int64_t offset = (*input_index0 < input_size - 1) ? 1 : 0;
*input_index1 = *input_index0 + offset;
*lambda1 = real_input_index - static_cast<T>(*input_index0);
constexpr T one = 1.0;
*lambda0 = one - *lambda1;
}
}
template <typename T>
inline std::string Vector2Str(const std::vector<T> &inputs) {
if (!inputs.empty()) {

View File

@ -86,6 +86,8 @@ constexpr auto kTensorScatterElements = "TensorScatterElements";
constexpr auto kExtractGlimpse = "ExtractGlimpse";
constexpr auto kUpsampleNearest3D = "UpsampleNearest3D";
constexpr auto kUpsampleNearest3DGrad = "UpsampleNearest3DGrad";
constexpr auto kUpsampleTrilinear3D = "UpsampleTrilinear3D";
constexpr auto kUpsampleTrilinear3DGrad = "UpsampleTrilinear3DGrad";
constexpr auto kEnvironCreate = "EnvironCreate";
constexpr auto kEnvironSet = "EnvironSet";
constexpr auto kEnvironGet = "EnvironGet";
@ -152,6 +154,8 @@ const std::map<std::string, std::string> kOpNameToAicpuOpNameMap{
{kUpsampleNearest3DGrad, "UpsampleNearest3dGrad"},
{kNameRangeV2, "Range"},
{kReLUV3, "Relu"},
{kUpsampleTrilinear3D, "UpsampleTrilinear3d"},
{kUpsampleTrilinear3DGrad, "UpsampleTrilinear3dGrad"},
{kStack, "Pack"},
{kUnstack, "Unpack"},
{kGather, "GatherV2"},

View File

@ -0,0 +1,163 @@
/**
* Copyright 2022 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 "plugin/device/cpu/kernel/upsample_trilinear_3d_cpu_kernel.h"
#include <string>
#include "kernel/common_utils.h"
#include "plugin/device/cpu/hal/device/cpu_device_address.h"
namespace mindspore {
namespace kernel {
namespace {
constexpr size_t kUpsampleTrilinear3DInputsNum = 1;
constexpr size_t kUpsampleTrilinear3DOutputNum = 1;
// GRAIN_SIZE for Parallel
constexpr size_t kGrainSize = 32768;
} // namespace
void UpsampleTrilinear3DCpuKernelMod::InitKernel(const CNodePtr &kernel_node) {
MS_EXCEPTION_IF_NULL(kernel_node);
kernel_name_ = common::AnfAlgo::GetCNodeName(kernel_node);
in_type_ = AnfAlgo::GetOutputDeviceDataType(kernel_node, kIndex0);
x_shape_ = AnfAlgo::GetInputDeviceShape(kernel_node, kIndex0);
y_shape_ = AnfAlgo::GetOutputDeviceShape(kernel_node, kIndex0);
if (x_shape_.size() != kDim5) {
MS_EXCEPTION(ValueError) << "For '" << kernel_name_ << "', the dimension of 'x' should be " << kDim5 << ", but got "
<< x_shape_.size();
}
attr_scales_ = common::AnfAlgo::GetNodeAttr<std::vector<float>>(kernel_node, kAttrScales);
if (attr_scales_.empty()) {
attr_scales_ = {0, 0, 0};
}
attr_align_corners_ = common::AnfAlgo::GetNodeAttr<bool>(kernel_node, kAttrAlignCorners);
}
bool UpsampleTrilinear3DCpuKernelMod::Launch(const std::vector<kernel::AddressPtr> &inputs,
const std::vector<kernel::AddressPtr> &,
const std::vector<kernel::AddressPtr> &outputs) {
CHECK_KERNEL_INPUTS_NUM(inputs.size(), kUpsampleTrilinear3DInputsNum, kernel_name_);
CHECK_KERNEL_OUTPUTS_NUM(outputs.size(), kUpsampleTrilinear3DOutputNum, kernel_name_);
bool res = false;
switch (in_type_) {
case kNumberTypeFloat16:
res = LaunchKernel<float16, float>(inputs, outputs);
break;
case kNumberTypeFloat32:
res = LaunchKernel<float, float>(inputs, outputs);
break;
case kNumberTypeFloat64:
res = LaunchKernel<double, double>(inputs, outputs);
break;
default:
MS_EXCEPTION(TypeError) << "For '" << kernel_name_
<< "', the dtype of 'x' should be float16, float32 or float64. But got "
<< TypeIdLabel(in_type_);
}
return res;
}
template <typename T, typename S>
bool UpsampleTrilinear3DCpuKernelMod::LaunchKernel(const std::vector<kernel::AddressPtr> &inputs,
const std::vector<kernel::AddressPtr> &outputs) {
// treat batch and channels as one dimension
int64_t channels = x_shape_[kIndex0] * x_shape_[kIndex1];
int64_t input_depth = x_shape_[kIndex2];
int64_t input_height = x_shape_[kIndex3];
int64_t input_width = x_shape_[kIndex4];
int64_t output_depth = y_shape_[kIndex2];
int64_t output_height = y_shape_[kIndex3];
int64_t output_width = y_shape_[kIndex4];
MS_EXCEPTION_IF_CHECK_FAIL(channels > 0 && output_depth > 0 && output_height > 0 && output_width > 0,
"Invalid output shape.");
auto x_ptr = reinterpret_cast<T *>(inputs[kIndex0]->addr);
auto y_ptr = reinterpret_cast<T *>(outputs[kIndex0]->addr);
if (input_depth == output_depth && input_height == output_height && input_width == output_width) {
auto cpy_ret = memcpy_s(y_ptr, outputs[kIndex0]->size, x_ptr, outputs[kIndex0]->size);
if (cpy_ret != EOK) {
MS_EXCEPTION(MemoryError) << "For " << kernel_name_ << ", memcpy_s to output failed.";
}
return true;
}
int64_t input_slice_size = input_depth * input_height * input_width;
int64_t output_slice_size = output_depth * output_height * output_width;
auto input_indexr_value = [=](int64_t n, int64_t d, int64_t h, int64_t w) {
return x_ptr[n * input_slice_size + d * input_height * input_width + h * input_width + w];
};
auto loop3d = [&](int64_t begin, int64_t end) {
const S depth_scale =
AreaPixelComputeScale<S>(input_depth, output_depth, attr_align_corners_, attr_scales_[kIndex0]);
const S height_scale =
AreaPixelComputeScale<S>(input_height, output_height, attr_align_corners_, attr_scales_[kIndex1]);
const S width_scale =
AreaPixelComputeScale<S>(input_width, output_width, attr_align_corners_, attr_scales_[kIndex2]);
int64_t id0(0), id1(0), ih0(0), ih1(0), iw0(0), iw1(0);
S d0lambda(0), d1lambda(0), h0lambda(0), h1lambda(0), w0lambda(0), w1lambda(0);
for (int64_t n = begin; n < end; ++n) {
for (int64_t od = 0; od < output_depth; ++od) {
ComputeSourceIndexAndLambda(&id0, &id1, &d0lambda, &d1lambda, depth_scale, od, input_depth, output_depth,
attr_align_corners_);
for (int64_t oh = 0; oh < output_height; ++oh) {
ComputeSourceIndexAndLambda(&ih0, &ih1, &h0lambda, &h1lambda, height_scale, oh, input_height, output_height,
attr_align_corners_);
for (int64_t ow = 0; ow < output_width; ++ow) {
ComputeSourceIndexAndLambda(&iw0, &iw1, &w0lambda, &w1lambda, width_scale, ow, input_width, output_width,
attr_align_corners_);
auto i000 = static_cast<S>(input_indexr_value(n, id0, ih0, iw0));
auto i001 = static_cast<S>(input_indexr_value(n, id0, ih0, iw1));
auto i010 = static_cast<S>(input_indexr_value(n, id0, ih1, iw0));
auto i011 = static_cast<S>(input_indexr_value(n, id0, ih1, iw1));
auto i100 = static_cast<S>(input_indexr_value(n, id1, ih0, iw0));
auto i101 = static_cast<S>(input_indexr_value(n, id1, ih0, iw1));
auto i110 = static_cast<S>(input_indexr_value(n, id1, ih1, iw0));
auto i111 = static_cast<S>(input_indexr_value(n, id1, ih1, iw1));
double w000 = static_cast<double>(d0lambda) * h0lambda * w0lambda;
double w001 = static_cast<double>(d0lambda) * h0lambda * w1lambda;
double w010 = static_cast<double>(d0lambda) * h1lambda * w0lambda;
double w011 = static_cast<double>(d0lambda) * h1lambda * w1lambda;
double w100 = static_cast<double>(d1lambda) * h0lambda * w0lambda;
double w101 = static_cast<double>(d1lambda) * h0lambda * w1lambda;
double w110 = static_cast<double>(d1lambda) * h1lambda * w0lambda;
double w111 = static_cast<double>(d1lambda) * h1lambda * w1lambda;
y_ptr[n * output_slice_size + od * output_height * output_width + oh * output_width + ow] =
static_cast<T>(w000 * i000 + w001 * i001 + w010 * i010 + w011 * i011 + w100 * i100 + w101 * i101 +
w110 * i110 + w111 * i111);
}
}
}
}
};
float block_size =
SizeToLong(kGrainSize) > output_slice_size ? static_cast<float>(kGrainSize / output_slice_size) : 1.0;
CPUKernelUtils::ParallelFor(loop3d, channels, block_size);
return true;
}
std::vector<KernelAttr> UpsampleTrilinear3DCpuKernelMod::GetOpSupport() {
static std::vector<KernelAttr> support_list = {
KernelAttr().AddInputAttr(kNumberTypeFloat16).AddOutputAttr(kNumberTypeFloat16),
KernelAttr().AddInputAttr(kNumberTypeFloat32).AddOutputAttr(kNumberTypeFloat32),
KernelAttr().AddInputAttr(kNumberTypeFloat64).AddOutputAttr(kNumberTypeFloat64)};
return support_list;
}
MS_KERNEL_FACTORY_REG(NativeCpuKernelMod, UpsampleTrilinear3D, UpsampleTrilinear3DCpuKernelMod);
} // namespace kernel
} // namespace mindspore

View File

@ -0,0 +1,56 @@
/**
* Copyright 2022 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_CCSRC_BACKEND_KERNEL_COMPILER_CPU_UPSAMLE_TRILINEAR_3D_CPU_KERNEL_H_
#define MINDSPORE_CCSRC_BACKEND_KERNEL_COMPILER_CPU_UPSAMLE_TRILINEAR_3D_CPU_KERNEL_H_
#include <algorithm>
#include <map>
#include <memory>
#include <vector>
#include "plugin/device/cpu/kernel/cpu_kernel.h"
#include "kernel/common_utils.h"
#include "plugin/factory/ms_factory.h"
namespace mindspore {
namespace kernel {
class UpsampleTrilinear3DCpuKernelMod : public DeprecatedNativeCpuKernelMod {
public:
UpsampleTrilinear3DCpuKernelMod() = default;
~UpsampleTrilinear3DCpuKernelMod() 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;
protected:
std::vector<KernelAttr> GetOpSupport() override;
private:
template <typename T, typename AccT>
bool LaunchKernel(const std::vector<AddressPtr> &inputs, const std::vector<AddressPtr> &outputs);
TypeId in_type_{kTypeUnknown};
std::vector<int64_t> x_shape_;
std::vector<int64_t> y_shape_;
std::vector<float> attr_scales_;
bool attr_align_corners_{false};
};
} // namespace kernel
} // namespace mindspore
#endif // MINDSPORE_CCSRC_BACKEND_KERNEL_COMPILER_CPU_UPSAMLE_TRILINEAR_3D_CPU_KERNEL_H_

View File

@ -0,0 +1,179 @@
/**
* Copyright 2022 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 "plugin/device/cpu/kernel/upsample_trilinear_3d_grad_cpu_kernel.h"
#include <string>
#include "kernel/common_utils.h"
#include "plugin/device/cpu/hal/device/cpu_device_address.h"
namespace mindspore {
namespace kernel {
namespace {
constexpr size_t kUpsampleTrilinear3DGradInputsNum = 1;
constexpr size_t kUpsampleTrilinear3DGradOutputNum = 1;
// GRAIN_SIZE for Parallel
constexpr size_t kGrainSize = 32768;
} // namespace
void UpsampleTrilinear3DGradCpuKernelMod::InitKernel(const CNodePtr &kernel_node) {
MS_EXCEPTION_IF_NULL(kernel_node);
kernel_name_ = common::AnfAlgo::GetCNodeName(kernel_node);
in_type_ = AnfAlgo::GetOutputDeviceDataType(kernel_node, kIndex0);
// the input grad of backward process is the output of forward process
output_shape_ = AnfAlgo::GetInputDeviceShape(kernel_node, kIndex0);
input_shape_ = AnfAlgo::GetOutputDeviceShape(kernel_node, kIndex0);
if (output_shape_.size() != kDim5) {
MS_EXCEPTION(ValueError) << "For '" << kernel_name_ << "', the dimension of 'grad_out' should be " << kDim5
<< ", but got " << output_shape_.size();
}
attr_scales_ = common::AnfAlgo::GetNodeAttr<std::vector<float>>(kernel_node, kAttrScales);
if (attr_scales_.empty()) {
attr_scales_ = {0, 0, 0};
}
attr_align_corners_ = common::AnfAlgo::GetNodeAttr<bool>(kernel_node, kAttrAlignCorners);
}
bool UpsampleTrilinear3DGradCpuKernelMod::Launch(const std::vector<kernel::AddressPtr> &inputs,
const std::vector<kernel::AddressPtr> &,
const std::vector<kernel::AddressPtr> &outputs) {
CHECK_KERNEL_INPUTS_NUM(inputs.size(), kUpsampleTrilinear3DGradInputsNum, kernel_name_);
CHECK_KERNEL_OUTPUTS_NUM(outputs.size(), kUpsampleTrilinear3DGradOutputNum, kernel_name_);
bool res = false;
switch (in_type_) {
case kNumberTypeFloat16:
res = LaunchKernel<float16, float>(inputs, outputs);
break;
case kNumberTypeFloat32:
res = LaunchKernel<float, float>(inputs, outputs);
break;
case kNumberTypeFloat64:
res = LaunchKernel<double, double>(inputs, outputs);
break;
default:
MS_EXCEPTION(TypeError) << "For '" << kernel_name_
<< "', the dtype of 'x' should be float16, float32 or float64. But got "
<< TypeIdLabel(in_type_);
break;
}
return res;
}
template <typename T, typename S>
bool UpsampleTrilinear3DGradCpuKernelMod::LaunchKernel(const std::vector<kernel::AddressPtr> &inputs,
const std::vector<kernel::AddressPtr> &outputs) {
// the input grad of backward process is the output of forward process
auto grad_output_ptr = reinterpret_cast<T *>(inputs[kIndex0]->addr);
const int64_t total = CPUKernelUtils::CalcElementNum(input_shape_);
S *grad_input_ptr = nullptr;
bool is_fp16 = std::is_same<T, float16>::value;
// define for fp16
std::vector<S> grad_input_copy(1);
if (is_fp16) {
grad_input_copy.resize(total, 0);
grad_input_ptr = grad_input_copy.data();
} else {
grad_input_ptr = reinterpret_cast<S *>(outputs[kIndex0]->addr);
std::fill_n(grad_input_ptr, total, S(0));
}
// treat nbatch and channels as one dimension
int64_t channels = input_shape_[kIndex0] * input_shape_[kIndex1];
int64_t input_depth = input_shape_[kIndex2];
int64_t input_height = input_shape_[kIndex3];
int64_t input_width = input_shape_[kIndex4];
int64_t output_depth = output_shape_[kIndex2];
int64_t output_height = output_shape_[kIndex3];
int64_t output_width = output_shape_[kIndex4];
int64_t output_slice_size = output_depth * output_height * output_width;
int64_t input_slice_size = input_depth * input_height * input_width;
MS_EXCEPTION_IF_CHECK_FAIL(channels != 0 && output_depth != 0 && output_height != 0 && output_width != 0,
"Invalid output shape.");
auto input_index = [=](int64_t c_idx, int64_t d_idx, int64_t h_idx, int64_t w_idx) {
return c_idx * input_slice_size + d_idx * input_height * input_width + h_idx * input_width + w_idx;
};
auto loop3d = [&](int64_t begin, int64_t end) {
const S depth_scale =
AreaPixelComputeScale<S>(input_depth, output_depth, attr_align_corners_, attr_scales_[kIndex0]);
const S height_scale =
AreaPixelComputeScale<S>(input_height, output_height, attr_align_corners_, attr_scales_[kIndex1]);
const S width_scale =
AreaPixelComputeScale<S>(input_width, output_width, attr_align_corners_, attr_scales_[kIndex2]);
int64_t id0{0}, id1{0}, ih0{0}, ih1{0}, iw0{0}, iw1{0};
S d0lambda{0}, d1lambda{0}, h0lambda{0}, h1lambda{0}, w0lambda{0}, w1lambda{0};
for (int64_t c_idx = begin; c_idx < end; ++c_idx) {
for (int64_t od = 0; od < output_depth; ++od) {
ComputeSourceIndexAndLambda(&id0, &id1, &d0lambda, &d1lambda, depth_scale, od, input_depth, output_depth,
attr_align_corners_);
for (int64_t oh = 0; oh < output_height; ++oh) {
ComputeSourceIndexAndLambda(&ih0, &ih1, &h0lambda, &h1lambda, height_scale, oh, input_height, output_height,
attr_align_corners_);
for (int64_t ow = 0; ow < output_width; ++ow) {
ComputeSourceIndexAndLambda(&iw0, &iw1, &w0lambda, &w1lambda, width_scale, ow, input_width, output_width,
attr_align_corners_);
auto grad_output_value = static_cast<S>(
grad_output_ptr[c_idx * output_slice_size + od * output_height * output_width + oh * output_width + ow]);
double w000 = static_cast<double>(d0lambda) * h0lambda * w0lambda;
double w001 = static_cast<double>(d0lambda) * h0lambda * w1lambda;
double w010 = static_cast<double>(d0lambda) * h1lambda * w0lambda;
double w011 = static_cast<double>(d0lambda) * h1lambda * w1lambda;
double w100 = static_cast<double>(d1lambda) * h0lambda * w0lambda;
double w101 = static_cast<double>(d1lambda) * h0lambda * w1lambda;
double w110 = static_cast<double>(d1lambda) * h1lambda * w0lambda;
double w111 = static_cast<double>(d1lambda) * h1lambda * w1lambda;
grad_input_ptr[input_index(c_idx, id0, ih0, iw0)] += static_cast<S>(w000 * grad_output_value);
grad_input_ptr[input_index(c_idx, id0, ih0, iw1)] += static_cast<S>(w001 * grad_output_value);
grad_input_ptr[input_index(c_idx, id0, ih1, iw0)] += static_cast<S>(w010 * grad_output_value);
grad_input_ptr[input_index(c_idx, id0, ih1, iw1)] += static_cast<S>(w011 * grad_output_value);
grad_input_ptr[input_index(c_idx, id1, ih0, iw0)] += static_cast<S>(w100 * grad_output_value);
grad_input_ptr[input_index(c_idx, id1, ih0, iw1)] += static_cast<S>(w101 * grad_output_value);
grad_input_ptr[input_index(c_idx, id1, ih1, iw0)] += static_cast<S>(w110 * grad_output_value);
grad_input_ptr[input_index(c_idx, id1, ih1, iw1)] += static_cast<S>(w111 * grad_output_value);
}
}
}
}
};
float block_size =
SizeToLong(kGrainSize) > output_slice_size ? static_cast<float>(kGrainSize / output_slice_size) : 1.0;
CPUKernelUtils::ParallelFor(loop3d, channels, block_size);
// memcopy and cast for fp16
if (is_fp16) {
T *real_input_ptr = reinterpret_cast<T *>(outputs[kIndex0]->addr);
for (int64_t idx = 0; idx < total; ++idx) {
real_input_ptr[idx] = static_cast<T>(grad_input_ptr[idx]);
}
}
return true;
}
std::vector<KernelAttr> UpsampleTrilinear3DGradCpuKernelMod::GetOpSupport() {
static std::vector<KernelAttr> support_list = {
KernelAttr().AddInputAttr(kNumberTypeFloat16).AddOutputAttr(kNumberTypeFloat16),
KernelAttr().AddInputAttr(kNumberTypeFloat32).AddOutputAttr(kNumberTypeFloat32),
KernelAttr().AddInputAttr(kNumberTypeFloat64).AddOutputAttr(kNumberTypeFloat64)};
return support_list;
}
MS_KERNEL_FACTORY_REG(NativeCpuKernelMod, UpsampleTrilinear3DGrad, UpsampleTrilinear3DGradCpuKernelMod);
} // namespace kernel
} // namespace mindspore

View File

@ -0,0 +1,56 @@
/**
* Copyright 2022 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_CCSRC_BACKEND_KERNEL_COMPILER_CPU_UPSAMLE_TRILINEAR_3D_GRAD_CPU_KERNEL_H_
#define MINDSPORE_CCSRC_BACKEND_KERNEL_COMPILER_CPU_UPSAMLE_TRILINEAR_3D_GRAD_CPU_KERNEL_H_
#include <algorithm>
#include <map>
#include <memory>
#include <vector>
#include "kernel/common_utils.h"
#include "plugin/device/cpu/kernel/cpu_kernel.h"
#include "plugin/factory/ms_factory.h"
namespace mindspore {
namespace kernel {
class UpsampleTrilinear3DGradCpuKernelMod : public DeprecatedNativeCpuKernelMod {
public:
UpsampleTrilinear3DGradCpuKernelMod() = default;
~UpsampleTrilinear3DGradCpuKernelMod() 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;
protected:
std::vector<KernelAttr> GetOpSupport() override;
private:
template <typename T, typename S>
bool LaunchKernel(const std::vector<AddressPtr> &inputs, const std::vector<AddressPtr> &outputs);
TypeId in_type_{kTypeUnknown};
std::vector<int64_t> input_shape_;
std::vector<int64_t> output_shape_;
std::vector<float> attr_scales_;
bool attr_align_corners_{false};
};
} // namespace kernel
} // namespace mindspore
#endif // MINDSPORE_CCSRC_BACKEND_KERNEL_COMPILER_CPU_UPSAMLE_TRILINEAR_3D_GRAD_CPU_KERNEL_H_

View File

@ -115,9 +115,8 @@ abstract::ShapePtr UpsampleTrilinear3DGradInferShape(const PrimitivePtr &primiti
TypePtr UpsampleTrilinear3DGradInferType(const PrimitivePtr &primitive,
const std::vector<AbstractBasePtr> &input_args) {
std::set<TypePtr> valid_types = {kFloat16, kFloat32};
TypePtr grad_type = input_args[kInputIndex0]->BuildType();
return CheckAndConvertUtils::CheckTensorTypeValid("grad", grad_type, valid_types, primitive->name());
return CheckAndConvertUtils::CheckTensorTypeValid("grad", grad_type, common_float_types, primitive->name());
}
} // namespace

View File

@ -1,47 +1,47 @@
/**
* Copyright 2022 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_CORE_OPS_GRAD_UPSAMPLE_TRILINEAR_3D_GRAD_H
#define MINDSPORE_CORE_OPS_GRAD_UPSAMPLE_TRILINEAR_3D_GRAD_H
#include <map>
#include <memory>
#include <string>
#include <vector>
#include "ops/base_operator.h"
#include "mindapi/base/types.h"
namespace mindspore {
namespace ops {
constexpr auto kNameUpsampleTrilinear3DGrad = "UpsampleTrilinear3DGrad";
class MIND_API UpsampleTrilinear3DGrad : public BaseOperator {
public:
MIND_API_BASE_MEMBER(UpsampleTrilinear3DGrad);
UpsampleTrilinear3DGrad() : BaseOperator(kNameUpsampleTrilinear3DGrad) { InitIOName({"grad"}, {"dx"}); }
bool get_align_corners() const;
std::vector<int64_t> get_out_spatial_size() const;
std::vector<int64_t> get_grad_spatial_size() const;
std::vector<float> get_scale_factors() const;
};
abstract::AbstractBasePtr UpsampleTrilinear3DGradInfer(const abstract::AnalysisEnginePtr &,
const PrimitivePtr &primitive,
const std::vector<abstract::AbstractBasePtr> &input_args);
using PrimUpsampleTrilinear3DGrad = std::shared_ptr<UpsampleTrilinear3DGrad>;
} // namespace ops
} // namespace mindspore
#endif // MINDSPORE_CORE_OPS_GRAD_UPSAMPLE_TRILINEAR_3D_GRAD_H
/**
* Copyright 2022 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_CORE_OPS_GRAD_UPSAMPLE_TRILINEAR_3D_GRAD_H
#define MINDSPORE_CORE_OPS_GRAD_UPSAMPLE_TRILINEAR_3D_GRAD_H
#include <map>
#include <memory>
#include <string>
#include <vector>
#include "ops/base_operator.h"
#include "mindapi/base/types.h"
namespace mindspore {
namespace ops {
constexpr auto kNameUpsampleTrilinear3DGrad = "UpsampleTrilinear3DGrad";
class MIND_API UpsampleTrilinear3DGrad : public BaseOperator {
public:
MIND_API_BASE_MEMBER(UpsampleTrilinear3DGrad);
UpsampleTrilinear3DGrad() : BaseOperator(kNameUpsampleTrilinear3DGrad) { InitIOName({"grad"}, {"dx"}); }
bool get_align_corners() const;
std::vector<int64_t> get_out_spatial_size() const;
std::vector<int64_t> get_grad_spatial_size() const;
std::vector<float> get_scale_factors() const;
};
abstract::AbstractBasePtr UpsampleTrilinear3DGradInfer(const abstract::AnalysisEnginePtr &,
const PrimitivePtr &primitive,
const std::vector<abstract::AbstractBasePtr> &input_args);
using PrimUpsampleTrilinear3DGrad = std::shared_ptr<UpsampleTrilinear3DGrad>;
} // namespace ops
} // namespace mindspore
#endif // MINDSPORE_CORE_OPS_GRAD_UPSAMPLE_TRILINEAR_3D_GRAD_H

View File

@ -41,6 +41,7 @@ const std::set<TypePtr> common_valid_types_with_complex_and_bool = {
kInt8, kInt16, kInt32, kInt64, kUInt8, kUInt16, kUInt32,
kUInt64, kFloat16, kFloat32, kFloat64, kComplex64, kComplex128, kBool};
const std::set<TypePtr> common_float_types = {kFloat16, kFloat32, kFloat64};
const std::set<TypePtr> all_types = {
kBool, kInt, kInt8, kInt16, kInt32, kInt64, kUInt, kUInt8,
kUInt16, kUInt32, kUInt64, kFloat, kFloat16, kFloat32, kFloat64, kComplex64,

View File

@ -15,11 +15,15 @@
*/
#include "ops/upsample_trilinear_3d.h"
#include <algorithm>
#include <memory>
#include <set>
#include <string>
#include <vector>
#include "abstract/ops/primitive_infer_map.h"
#include "ops/op_utils.h"
#include "mindapi/src/helper.h"
#include "utils/check_convert_utils.h"
#include "mindapi/src/helper.h"
namespace mindspore {
namespace ops {
@ -36,81 +40,70 @@ void CheckDims(string check_dim_name, string op_name, std::vector<T> check_vecto
abstract::ShapePtr UpsampleTrilinear3DInferShape(const PrimitivePtr &primitive,
const std::vector<AbstractBasePtr> &input_args) {
string op_name = primitive->name();
MS_EXCEPTION_IF_NULL(input_args[kInputIndex0]);
auto input_shape = CheckAndConvertUtils::ConvertShapePtrToShapeMap(input_args[kInputIndex0]->BuildShape())[kShape];
auto input_shape_ptr = input_args[kInputIndex0]->BuildShape();
const size_t kDimSize5 = 5;
if (input_shape.size() != kDimSize5) {
MS_EXCEPTION(TypeError) << "input_shape of UpsampleTrilinear3D must be 5, but got" << input_shape.size();
}
auto prim_name = primitive->name();
auto x_shape = CheckAndConvertUtils::ConvertShapePtrToShapeMap(input_args[kInputIndex0]->BuildShape())[kShape];
const size_t kOutputSizeDims = 3;
const size_t kScalesDims = 3;
auto output_size = GetValue<std::vector<int64_t>>(primitive->GetAttr("output_size"));
auto scales = GetValue<std::vector<float>>(primitive->GetAttr("scales"));
if (output_size.empty() && scales.empty()) {
MS_EXCEPTION(ValueError) << "For '" << op_name << "', either output_size or scales should be defined.";
(void)CheckAndConvertUtils::CheckInteger("dimension of x", SizeToLong(x_shape.size()), kEqual, SizeToLong(kDim5),
prim_name);
auto output_size_ptr = primitive->GetAttr(kOutputSize);
MS_EXCEPTION_IF_NULL(output_size_ptr);
auto output_size = GetValue<std::vector<int64_t>>(output_size_ptr);
auto scales_ptr = primitive->GetAttr(kScales);
MS_EXCEPTION_IF_NULL(scales_ptr);
auto scales = GetValue<std::vector<float>>(scales_ptr);
ShapeVector output_shape;
output_shape.emplace_back(x_shape[kInputIndex0]);
output_shape.emplace_back(x_shape[kInputIndex1]);
if (!output_size.empty() && scales.empty()) {
(void)CheckAndConvertUtils::CheckPositiveVector(kOutputSize, output_size, prim_name);
(void)CheckAndConvertUtils::CheckInteger("the elements number of output_size", SizeToLong(output_size.size()),
kEqual, SizeToLong(kDim3), prim_name);
output_shape.insert(output_shape.end(), output_size.begin(), output_size.end());
} else if (output_size.empty() && !scales.empty()) {
(void)CheckAndConvertUtils::CheckPositiveVector(kScales, scales, prim_name);
(void)CheckAndConvertUtils::CheckInteger("the elements number of scales", SizeToLong(scales.size()), kEqual,
SizeToLong(kDim3), prim_name);
for (size_t idx = 0; idx < kDim3; ++idx) {
output_shape.emplace_back(int64_t(floor(x_shape[idx + kDim2] * scales[idx])));
}
} else if (output_size.empty() && scales.empty()) {
MS_EXCEPTION(ValueError) << "For " << prim_name << ", only one of 'scales' and 'output_size' can be specified."
<< " But get both empty or None.";
} else if (!output_size.empty() && !scales.empty()) {
MS_EXCEPTION(ValueError) << "For '" << op_name << "', only one of output_size or scales should be defined.";
MS_EXCEPTION(ValueError) << "For " << prim_name << ", only one of 'scales' and 'output_size' can be specified."
<< " But get both.";
}
if (!output_size.empty() && output_size.size() != kOutputSizeDims) {
MS_EXCEPTION(ValueError) << "For '" << op_name << "', output_size must be size of 3, but got "
<< std::to_string(output_size.size()) << ".";
}
if (!scales.empty() && scales.size() != kScalesDims) {
MS_EXCEPTION(ValueError) << "For '" << op_name << "', scales must be size of 3, but got "
<< std::to_string(scales.size()) << ".";
}
string name_ = "scales";
std::vector<int64_t> output_shape(input_shape.size());
output_shape[0] = input_shape[0];
output_shape[1] = input_shape[1];
if (output_size.empty()) {
CheckDims(name_, op_name, scales);
output_shape[kInputIndex2] = static_cast<int64_t>(std::floor(input_shape[kInputIndex2] * scales[kInputIndex0]));
output_shape[kInputIndex3] = static_cast<int64_t>(std::floor(input_shape[kInputIndex3] * scales[kInputIndex1]));
output_shape[kInputIndex4] = static_cast<int64_t>(std::floor(input_shape[kInputIndex4] * scales[kInputIndex2]));
} else {
name_ = "output_size";
CheckDims(name_, op_name, output_size);
output_shape[kInputIndex2] = output_size[kInputIndex0];
output_shape[kInputIndex3] = output_size[kInputIndex1];
output_shape[kInputIndex4] = output_size[kInputIndex2];
}
if (input_shape_ptr->IsDynamic()) {
return std::make_shared<abstract::Shape>(output_shape);
}
name_ = "output_shape";
CheckDims(name_, op_name, output_shape);
constexpr auto name_ = "output_shape";
CheckDims(name_, prim_name, output_shape);
return std::make_shared<abstract::Shape>(output_shape);
}
TypePtr UpsampleTrilinear3DInferType(const PrimitivePtr &primitive, const std::vector<AbstractBasePtr> &input_args) {
const std::set<TypePtr> valid_types = {kFloat16, kFloat32};
TypePtr input_type = input_args[kInputIndex0]->BuildType();
return CheckAndConvertUtils::CheckTypeValid("x", input_type, valid_types, primitive->name());
return CheckAndConvertUtils::CheckTensorTypeValid("x", input_args[kInputIndex0]->BuildType(), common_float_types,
primitive->name());
}
} // namespace
MIND_API_OPERATOR_IMPL(UpsampleTrilinear3D, BaseOperator);
AbstractBasePtr UpsampleTrilinear3DInfer(const abstract::AnalysisEnginePtr &, const PrimitivePtr &primitive,
const std::vector<AbstractBasePtr> &input_args) {
MS_EXCEPTION_IF_NULL(primitive);
const int64_t kInputsNum = 1;
CheckAndConvertUtils::CheckInputArgs(input_args, kEqual, kInputsNum, primitive->name());
auto prim_name = primitive->name();
constexpr int64_t input_num = 1;
CheckAndConvertUtils::CheckInputArgs(input_args, kEqual, input_num, prim_name);
auto infer_type = UpsampleTrilinear3DInferType(primitive, input_args);
auto infer_shape = UpsampleTrilinear3DInferShape(primitive, input_args);
return abstract::MakeAbstract(infer_shape, infer_type);
}
std::vector<int64_t> UpsampleTrilinear3D::get_out_spatial_size() const {
auto value_ptr = this->GetAttr("output_size");
auto value_ptr = this->GetAttr(kOutputSize);
return GetValue<std::vector<int64_t>>(value_ptr);
}
std::vector<float> UpsampleTrilinear3D::get_scale_factors() const {
auto value_ptr = this->GetAttr("scales");
auto value_ptr = this->GetAttr(kScales);
return GetValue<std::vector<float>>(value_ptr);
}
bool UpsampleTrilinear3D::get_align_corners() const {
@ -118,6 +111,7 @@ bool UpsampleTrilinear3D::get_align_corners() const {
return GetValue<bool>(value_ptr);
}
MIND_API_OPERATOR_IMPL(UpsampleTrilinear3D, BaseOperator);
REGISTER_PRIMITIVE_EVAL_IMPL(UpsampleTrilinear3D, prim::kPrimUpsampleTrilinear3D, UpsampleTrilinear3DInfer, nullptr,
true);
} // namespace ops

View File

@ -274,7 +274,7 @@ class Validator:
@staticmethod
def check_positive_int_sequence(sequence, arg_name=None, prim_name=None):
"""
Check argument is positive sequence, which mean all element > 0 in sequence.
Check argument is positive int sequence, which mean all element > 0 in sequence.
Usage:
- sequence = check_positive_int_sequence(sequence)

View File

@ -36,6 +36,8 @@ from ..operations._grad_ops import FractionalAvgPoolGrad
from ..operations.nn_ops import MultiMarginLoss
from ..operations.nn_ops import MultilabelMarginLoss
from ..operations.nn_ops import NthElement
from ..operations.nn_ops import UpsampleTrilinear3D
from ..operations._grad_ops import UpsampleTrilinear3DGrad
from ..operations.nn_ops import PSROIPooling
from ..operations._grad_ops import PSROIPoolingGrad
from ..operations.nn_ops import AvgPoolV1
@ -172,6 +174,21 @@ def get_bprop_upsample_nearest_3d(self):
return bprop
@bprop_getters.register(UpsampleTrilinear3D)
def get_bprop_upsample_trilinear_3d(self):
"""Grad definition for `UpsampleTrilinear3D` operation."""
output_size = self.output_size
scales = self.scales
align_corners = self.align_corners
def bprop(x, out, dout):
input_size = P.Shape()(x)
grad_op = UpsampleTrilinear3DGrad(input_size, output_size, scales, align_corners)
dx = grad_op(dout)
return (dx,)
return bprop
@bprop_getters.register(GridSampler3D)
def get_bprop_grid_sampler_3d(self):
"""Grad definition for `GridSampler3D` operation."""

View File

@ -156,6 +156,8 @@ from .poisson import _poisson_aicpu
from .update_cache import _update_cache_aicpu
from .upsample_nearest_3d import _upsample_nearest_3d_aicpu
from .upsample_nearest_3d_grad import _upsample_nearest_3d_grad_aicpu
from .upsample_trilinear_3d import _upsample_trilinear_3d_aicpu
from .upsample_trilinear_3d_grad import _upsample_trilinear_3d_grad_aicpu
from .cache_swap_table import _cache_swap_table_aicpu
from .uniform_int import _uniform_int_aicpu
from .uniform_real import _uniform_real_aicpu

View File

@ -0,0 +1,35 @@
# Copyright 2022 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.
# ============================================================================
"""UpsampleTrilinear3D op"""
from mindspore.ops.op_info_register import op_info_register, AiCPURegOp, DataType
upsample_trilinear_3d_op_info = AiCPURegOp("UpsampleTrilinear3D") \
.fusion_type("OPAQUE") \
.attr("output_size", "listInt") \
.attr("scales", "listFloat") \
.attr("align_corners", "bool") \
.input(0, "x", "required") \
.output(0, "y", "required") \
.dtype_format(DataType.F16_Default, DataType.F16_Default) \
.dtype_format(DataType.F32_Default, DataType.F32_Default) \
.dtype_format(DataType.F64_Default, DataType.F64_Default) \
.get_op_info()
@op_info_register(upsample_trilinear_3d_op_info)
def _upsample_trilinear_3d_aicpu():
"""UpsampleTrilinear3D AiCPU register"""
return

View File

@ -0,0 +1,39 @@
# Copyright 2022 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.
# ============================================================================
"""UpsampleTrilinear3DGrad op"""
from mindspore.ops.op_info_register import op_info_register, AiCPURegOp, DataType
upsample_trilinear_3d_grad_op_info = AiCPURegOp("UpsampleTrilinear3DGrad") \
.fusion_type("OPAQUE") \
.attr("input_size", "listInt") \
.attr("output_size", "listInt") \
.attr("scales", "listFloat") \
.attr("align_corners", "bool") \
.input(0, "grad_output", "required") \
.output(0, "y", "required") \
.dtype_format(DataType.F16_Default, DataType.F16_Default) \
.dtype_format(DataType.F32_Default, DataType.F32_Default) \
.dtype_format(DataType.F64_Default, DataType.F64_Default) \
.get_op_info()
@op_info_register(upsample_trilinear_3d_grad_op_info)
def _upsample_trilinear_3d_grad_aicpu():
"""UpsampleTrilinear3DGrad AiCPU register"""
return

View File

@ -3011,6 +3011,84 @@ class MultiMarginLossGrad(Primitive):
self.init_prim_io_names(inputs=['y_grad', 'x', 'target', 'weight'], outputs=['x_grad'])
class UpsampleTrilinear3DGrad(Primitive):
r"""
Upsample the 3-D gradient data with trilinear interpolation algorithm.
Args:
input_size (Union[tuple[int], list[int]]): An required listInt.
contain 5 elements: [batch, channels, depth, height, width]. Must:
input_size[0] == grad_output_tensor_size[0]
input_size[1] == grad_output_tensor_size[1].
output_size (Union[tuple[int], list[int]]): An optional listInt. Defaults to none.
contain 3 elements: depth, height, width. The number of elements of 'output_size' should
be the same as the rank of input 'grad_output'.
Only one of 'scales' and 'output_size' can be specified. Must:
grad_output_tensor_size[2] == floor(input_size[2] * scales[0]) == output_size[0]
grad_output_tensor_size[3] == floor(input_size[3] * scales[1]) == output_size[1]
grad_output_tensor_size[4] == floor(input_size[4] * scales[2]) == output_size[2].
scales (Union[tuple[float], list[float]]): An optional listFloat. Defaults to none.
The scale array along each dimension, contain 3 elements: scale_depth, scale_height, scale_width.
The number of elements of 'scales' should be the same as the rank of input 'grad_output'.
One of 'scales' and 'output_size' MUST be specified and it is an error if both are specified.
align_corners (bool): An optional bool. Defaults to false.
Inputs:
- **grad_output** (Tensor) - A 5-D input tensor [N, C, D, H, W].
Must be one of the following types: [float16, float32, float64].
Outputs:
backprops Tensor - A Tensor with shape depends on intput_size and output_size/scales.
Must be one of the following types: [float16, float32, float64].
Raises:
TypeError: If dtype of `x` is not int [float16, float32, float64].
TypeError: If `input_size` is not list[int] or tuple[int].
TypeError: When `output_size` is not none and `output_size` is not list[int] or tuple[int].
TypeError: When `scales` is not none and `scales` is not list[float] or tuple[float].
TypeError: If type of `align_corners` is not bool.
ValueError: If any value of `output_size` is negative or zero when `output_size` is not empty.
ValueError: If any value of `scales` is negative or zero when `scales` is not empty.
ValueError: If shape of `x` is not 5D.
ValueError: If none of `scales` and `output_size` is specified or both specified.
ValueError: If size of `scales` is not equal 3 when `scales` is specified.
ValueError: If size of `output_size` is not equal 3 when `output_size` is specified.
TypeError: If `input_size` is not Union[tuple[int], list[int]].
ValueError: If any value of `input_size` is negative.
ValueError: If elements number of `input_size` is not 5.
Supported Platforms:
``Ascend`` ``CPU`` ``GPU``
"""
@prim_attr_register
def __init__(self, input_size, output_size=None, scales=None, align_corners=False):
"""Initialize UpsampleTrilinear3DGrad."""
self.init_prim_io_names(inputs=['grad_output'], outputs=['y'])
self.input_size = input_size
self.output_size = [] if output_size is None else output_size
self.scales = [] if scales is None else scales
self.align_corners = align_corners
validator.check_value_type("input_size", self.input_size, [list, tuple], self.name)
validator.check_equal_int(len(self.input_size), 5, "the dimension of input_size", self.name)
validator.check_value_type("output_size", self.output_size, [list, tuple], self.name)
validator.check_value_type("scales", self.scales, [list, tuple], self.name)
validator.check_bool(self.align_corners, self.name)
if len(self.output_size) == 3:
validator.check_positive_int_sequence(self.output_size, "output_size", self.name)
if len(self.scales) == 3:
validator.check_positive_float_sequence(self.scales, "scales", self.name)
if self.output_size == []:
validator.check_equal_int(len(self.scales), 3, 'size of scales', self.name)
if self.scales == []:
validator.check_equal_int(len(self.output_size), 3, 'size of output_size', self.name)
self.add_prim_attr('input_size', self.input_size)
self.add_prim_attr('output_size', self.output_size)
self.add_prim_attr('scales', self.scales)
self.add_prim_attr('align_corners', self.align_corners)
class GridSampler3DGrad(Primitive):
"""
Computes gradients for GridSampler3D operation.
@ -3433,67 +3511,6 @@ class GridSampler2DGrad(Primitive):
self.add_prim_attr('align_corners', align_corners)
class UpsampleTrilinear3DGrad(Primitive):
"""
Computes gradients for UpsampleTrilinear3DGrad operation.
Args:
input_size (Union[tuple[int], list[int]]): A list or tuple of int specifying the forward pass
input Tensor size, identical to the gradient tensor returned by this op.
output_size (Union[tuple[int], list[int]]): A list or tuple of int specifying the output
volumetric size, identical to the backprop gradient entering this op. Defaults to None.
scales (Union[tuple[float], list[float]]): A list or tuple of float specifying the upsampling factors.
Defaults to None.
align_corners (bool): An optional bool. If "true", the centers of the corner pixels of the input and output
tensors are aligned. Defaults to "false".
Inputs:
- **grad** (Tensor) - 5D tensor of shape :math:`(N, C, D_{grad}, H_{grad}, W_{grad})`. With float16 or
float32 data type.
Outputs:
- **dx** (Tensor) - 5D tensor of shape :math:`(N, C, D_{dx}, H_{dx}, W_{dx})`. With float16 or
float32 data type.
Raises:
TypeError: If data type of `grad` is not float16, float32.
TypeError: If `input_size` is not provided.
ValueError: If size of `grad` is not a 5D tensor.
ValueError: If `output_size` is a list or tuple and if `output_size` length is not 3.
ValueError: If `scales` is a list or tuple and if `scales` length is not 3.
ValueError: If both `output_size` and `scales` are None.
ValueError: If both `output_size` and `scales` are non-empty lists.
Supported Platforms:
``GPU``
"""
@prim_attr_register
def __init__(self, input_size, output_size=None, scales=None, align_corners=None):
self.init_prim_io_names(inputs=['grad'], outputs=['dx'])
if output_size is None:
output_size = []
if scales is None:
scales = []
if align_corners is None:
align_corners = False
validator.check_value_type('input_size', input_size, [list, tuple], self.name)
for item in input_size:
validator.check_value_type('input_size_item', item, int, self.name)
validator.check_value_type("output_size", output_size, [list, tuple], self.name)
for item in output_size:
validator.check_value_type('output_size_item', item, int, self.name)
validator.check_value_type("scales", scales, [list, tuple], self.name)
for item in scales:
validator.check_value_type('scales_item', item, float, self.name)
validator.check_value_type('align_corners', align_corners, bool, self.name)
self.add_prim_attr('input_size', input_size)
self.add_prim_attr('output_size', output_size)
self.add_prim_attr('scales', scales)
self.add_prim_attr('align_corners', align_corners)
class ResizeBicubicGrad(Primitive):
"""
Computes gradients for ResizeBicubicGrad operation.

View File

@ -3744,6 +3744,92 @@ class ResizeBilinear(PrimitiveWithInfer):
return input_dtype
class UpsampleTrilinear3D(Primitive):
r"""
Performs upsampling with trilinear interpolation across 3dims for 5dim inputs.
This operator scale up the volumetric input with specified `output_size` or `scales` factors,
using trilinear upscaling algorithm.
Note:
One of `scales` and `output_size` MUST be specified and it is an error if both are specified.
Args:
output_size (Union[tuple[int], list[int]]): A tuple or list of 3 int
elements :math:`(output\_depth, output\_height, output\_width)`.
Defaults to None. Only one of `scales` and `output_size` can be specified.
scales (Union[tuple[float], list[float]]): A tuple or list of 3 float
elements :math:`(scale\_depth, scale\_height, scale\_width)`. Defaults to None.
align_corners (bool): An optional bool. Defaults to false.
If true, the input and output tensors are aligned by the center points of their corner pixels,
preserving the values at the corner pixels.
If false, the input and output tensors are aligned by the corner points of their corner pixels,
and the interpolation use edge value padding for out of boundary values.
Inputs:
- **x** (Tensor) - A 5-D input tensor of shape :math:`(N, C, D_{in}, H_{in}, W_{in})`.
Must be one of the following types: float16, float32, float64.
Outputs:
- **y** (Tensor) - Upsampled output with the same data type as `x`.
Tensor of shape :math:`(N, C, D_{out}, H_{out}, W_{out})`.
Raises:
TypeError: When `output_size` is not none and `output_size` is not list[int] or tuple[int].
TypeError: When `scales` is not none and `scales` is not list[float] or tuple[float].
TypeError: If dtype of `x` is not in [float16, float32, float64].
TypeError: If type of `align_corners` is not bool.
ValueError: If any value of `output_size` is negative or zero when `output_size` is not empty.
ValueError: If any value of `scales` is negative or zero when `scales` is not empty.
ValueError: If shape of `x` is not 5D.
ValueError: If none of `scales` and `output_size` is specified or both specified.
ValueError: If size of `scales` is not equal 3 when `scales` is specified.
ValueError: If size of `output_size` is not equal 3 when `output_size` is specified.
Supported Platforms:
``Ascend`` ``CPU`` ``GPU``
Examples:
>>> ops = P.UpsampleTrilinear3D(output_size=[4, 64, 48])
>>> out = ops(Tensor(input_data=np.random.randn(2, 3, 4, 512, 256)))
>>> print(out.shape)
(2, 3, 4, 64, 48)
>>> ops = P.UpsampleTrilinear3D(output_size=[2, 4, 4])
>>> in_x = Tensor(np.arange(1, 5, dtype=np.float32).reshape((1, 1, 1, 2, 2)))
>>> out = ops(in_x)
>>> print(out)
[[[[[1. 1.25 1.75 2. ]
[1.5 1.75 2.25 2.5 ]
[2.5 2.75 3.25 3.5 ]
[3. 3.25 3.75 4. ]]
[[1. 1.25 1.75 2. ]
[1.5 1.75 2.25 2.5 ]
[2.5 2.75 3.25 3.5 ]
[3. 3.25 3.75 4. ]]]]]
"""
@prim_attr_register
def __init__(self, output_size=None, scales=None, align_corners=False):
"""Initialize UpsampleTrilinear3D."""
self.init_prim_io_names(inputs=['x'], outputs=['y'])
self.output_size = [] if output_size is None else output_size
self.scales = [] if scales is None else scales
self.align_corners = align_corners
validator.check_value_type("output_size", self.output_size, [list, tuple], self.name)
validator.check_value_type("scales", self.scales, [list, tuple], self.name)
validator.check_bool(self.align_corners, "align_corners", self.name)
if len(self.output_size) == 3:
validator.check_positive_int_sequence(self.output_size, "output_size", self.name)
if len(self.scales) == 3:
validator.check_positive_float_sequence(self.scales, "scales", self.name)
self.add_prim_attr('output_size', self.output_size)
self.add_prim_attr('scales', self.scales)
self.add_prim_attr('align_corners', self.align_corners)
class OneHot(Primitive):
r"""
Computes a one-hot tensor.
@ -10148,84 +10234,6 @@ class Pdist(Primitive):
self.init_prim_io_names(inputs=['x'], outputs=['y'])
class UpsampleTrilinear3D(Primitive):
r"""
Performs upsampling with trilinear interpolation across 3dims for 5dim inputs.
This operator scale up the volumetric input with specified `output_size` or `scales` factors,
using trilinear upscaling algorithm.
One of `output_size` or `scales` must be given, and cannot specify both.
Args:
output_size (Union[tuple[int], list[int]]): A list of int specifying the output volumetric size. Default: None.
scales (Union[tuple[float], list[float]]): A list of float specifying the upsampling factors. Default: None.
align_corners (bool): If true, rescale input by :math:`(new\_height - 1) / (height - 1)`,
which exactly aligns the 4 corners of images and resized images. If false,
rescale by :math:`new\_height / height`. Default: False.
Inputs:
- **x** (Tensor) - 5D tensor of shape :math:`(N, C, D_{in}, H_{in}, W_{in})`.
Outputs:
- **y** (Tensor) - Upsampled output with the same data type as `x`.
Tensor of shape :math:`(N, C, D_{out}, H_{out}, W_{out})`.
Raises:
TypeError: If `x` is not a 5D tensor.
TypeError: If data type of `x` is not float16, float32.
TypeError: If data type of `output_size` is not list(int).
TypeError: If data type of `scales` is not list(float).
TypeError: If `align_corners` is not a bool.
ValueError: If `output_size` is a list and if `output_size` length is not 3.
ValueError: If `scales` is a list and if `scales` length is not 3.
ValueError: If both `output_size` and `scales` are None.
ValueError: If both `output_size` and `scales` are non-empty lists.
Supported Platforms:
``GPU``
Examples:
>>> x = Tensor(np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16])
... .reshape([1, 1, 2, 2, 4]), mstype.float32)
>>> output_size = [3, 4, 5]
>>> net = ops.UpsampleTrilinear3D(output_size = output_size)
>>> output = net(x)
>>> print(output)
[[[[[ 1. 1.7 2.5 3.3 4.]
[ 2. 2.7 3.5 4.3 5.]
[ 4. 4.7 5.5 6.3 7.]
[ 5. 5.7 6.5 7.3 8.]]
[[ 5. 5.7 6.5 7.3 8.]
[ 6. 6.7 7.5 8.3 9.]
[ 8. 8.700001 9.5 10.3 11.]
[ 9. 9.700001 10.5 11.3 12.]]
[[ 9. 9.7 10.5 11.3 12.]
[10. 10.7 11.5 12.3 13.]
[12. 12.700001 13.5 14.3 15.]
[13. 13.700001 14.5 15.3 16.]]]]]
"""
@prim_attr_register
def __init__(self, output_size=None, scales=None, align_corners=False):
self.init_prim_io_names(inputs=['x'], outputs=['y'])
if output_size is None:
output_size = []
if scales is None:
scales = []
validator.check_value_type('output_size', output_size, [tuple, list], self.name)
for item in output_size:
validator.check_value_type('output_size_item', item, int, self.name)
validator.check_value_type('scales', scales, [tuple, list], self.name)
for item in scales:
validator.check_value_type('scales_item', item, float, self.name)
validator.check_value_type('align_corners', align_corners, bool, self.name)
self.add_prim_attr('output_size', output_size)
self.add_prim_attr('scales', scales)
self.add_prim_attr('align_corners', align_corners)
class UpsampleNearest3D(Primitive):
r"""
Performs nearest neighbor upsampling operation.

View File

@ -246,7 +246,7 @@ def test_upsample_nearest_3d_error():
"""
context.set_context(mode=context.GRAPH_MODE, device_target='GPU')
with pytest.raises(TypeError):
with pytest.raises(ValueError):
input_tensor = Tensor(np.ones((2, 2, 2, 2), dtype=np.float32))
net = UpsampleTrilinear3DNet(output_size=[3, 4, 5])
net(input_tensor)

View File

@ -116,6 +116,8 @@ from mindspore.ops.operations.nn_ops import UpsampleNearest3D
from mindspore.ops.operations._grad_ops import UpsampleNearest3DGrad
from mindspore.ops.operations.nn_ops import AvgPoolV1
from mindspore.ops.operations._grad_ops import AvgPoolGradV1
from mindspore.ops.operations.nn_ops import UpsampleTrilinear3D
from mindspore.ops.operations._grad_ops import UpsampleTrilinear3DGrad
from mindspore.ops.operations.nn_ops import MaxPoolV1
from mindspore.ops.operations.array_ops import NonZero
from mindspore.ops.operations._grad_ops import MaxPoolGradV1
@ -2730,6 +2732,14 @@ test_case_nn_ops = [
'desc_const': [Tensor(np.array([1, 2, 3, 4]).astype(np.int32))],
'desc_inputs': [],
'skip': ['backward']}),
('UpsampleTrilinear3D', {
'block': UpsampleTrilinear3D(output_size=[4, 64, 48]),
'desc_inputs': [([2, 3, 4, 512, 256], {'dtype': np.float32})],
'desc_bprop': [([2, 3, 4, 64, 48], {'dtype': np.float32})]}),
('UpsampleNearest3DGrad', {
'block': UpsampleTrilinear3DGrad(input_size=[2, 3, 4, 512, 256], output_size=[4, 64, 48], scales=None),
'desc_inputs': [([2, 3, 4, 64, 48], {'dtype': np.float32})],
'skip': ['backward']}),
('DropoutGenMask', {
'block': P.DropoutGenMask(),
'desc_const': [(2, 2), Tensor(0.5, mstype.float32)],