[GPU] Use int64_t type for axis in softmax (#12287)
This commit is contained in:
@@ -232,6 +232,7 @@ REGISTER_FACTORY(v8, RandomUniform)
|
||||
REGISTER_FACTORY(v8, MaxPool);
|
||||
REGISTER_FACTORY(v8, AdaptiveAvgPool);
|
||||
REGISTER_FACTORY(v8, AdaptiveMaxPool);
|
||||
REGISTER_FACTORY(v8, Softmax);
|
||||
|
||||
// ------------------------------ Supported v9 ops ------------------------------ //
|
||||
REGISTER_FACTORY(v9, SoftSign)
|
||||
|
||||
@@ -25,24 +25,13 @@ namespace cldnn {
|
||||
struct softmax : public primitive_base<softmax> {
|
||||
CLDNN_DECLARE_PRIMITIVE(softmax)
|
||||
|
||||
/// @brief Enum type to specify softmax's normalization scope (see #dimension).
|
||||
enum dimension_t {
|
||||
normalize_b,
|
||||
normalize_f,
|
||||
normalize_x,
|
||||
normalize_y,
|
||||
normalize_z,
|
||||
normalize_fyx,
|
||||
normalize_all
|
||||
};
|
||||
|
||||
/// @brief Constructs softmax primitive.
|
||||
/// @param id This primitive id.
|
||||
/// @param input Input primitive id.
|
||||
/// @param dimension Defines a scope of normalization (see #dimension).
|
||||
/// @param dimension Defines a scope of normalization
|
||||
softmax(const primitive_id& id,
|
||||
const primitive_id& input,
|
||||
const dimension_t dimension = normalize_fyx,
|
||||
const int64_t dimension = 1,
|
||||
const primitive_id& ext_prim_id = "",
|
||||
const padding& output_padding = padding())
|
||||
: primitive_base(id, {input}, ext_prim_id, output_padding), dimension(dimension) {}
|
||||
@@ -51,13 +40,12 @@ struct softmax : public primitive_base<softmax> {
|
||||
/// @details
|
||||
/// Being given a 4-dimensional input, which consists of b,f,y,x dimensions, softmax normalizes data which are divided into multiple independent sets.
|
||||
/// Specific behaviour is determined by this parameter, as follows:
|
||||
/// - when set to @link softmax::dimension_t softmax::normalize_x @endlink each input row is normalized independently,
|
||||
/// - when set to @link softmax::dimension_t softmax::normalize_y @endlink each input column is normalized independently,
|
||||
/// - when set to @link softmax::dimension_t softmax::normalize_z @endlink each input z-coordinate is normalized independently,
|
||||
/// - when set to @link softmax::dimension_t softmax::normalize_f @endlink each in-depth vector of input is normalized independently,
|
||||
/// - when set to @link softmax::dimension_t softmax::normalize_fyx @endlink each 3d image within input is normalized independently,
|
||||
/// - when set to @link softmax::dimension_t softmax::normalize_all @endlink everything is normalized,
|
||||
dimension_t dimension;
|
||||
/// - when softmax dimension is set to 0 (b dim) each batch vector of input is normalized independently,
|
||||
/// - when softmax dimension is set to 1 (f dim) each in-depth vector of input is normalized independently,
|
||||
/// - when softmax dimension is set to 2 (y dim) each input column is normalized independently,
|
||||
/// - when softmax dimension is set to 3 (x dim) each input row is normalized independently.
|
||||
|
||||
int64_t dimension;
|
||||
};
|
||||
/// @}
|
||||
/// @}
|
||||
|
||||
@@ -925,7 +925,7 @@ void prepare_primitive_fusing::fuse_simple_primitives(program &p) {
|
||||
should_fuse |= input_data.is_type<scale>() && quantize_node.get_scale_shift_opt();
|
||||
|
||||
should_fuse |= input_data.is_type<softmax>() &&
|
||||
input_data.as<softmax>().get_primitive()->dimension == softmax::dimension_t::normalize_f &&
|
||||
input_data.as<softmax>().get_primitive()->dimension == 1 &&
|
||||
per_tensor_values;
|
||||
|
||||
|
||||
|
||||
@@ -13,6 +13,28 @@
|
||||
namespace cldnn {
|
||||
namespace ocl {
|
||||
|
||||
static inline kernel_selector::softmax_dim GetSoftmaxDim(int64_t axis, size_t rank) {
|
||||
if (axis < 0) {
|
||||
axis += rank;
|
||||
}
|
||||
switch (axis) {
|
||||
case 0: return kernel_selector::softmax_dim::BATCH;
|
||||
case 1: return kernel_selector::softmax_dim::FEATURE;
|
||||
case 2:
|
||||
if (rank > 4)
|
||||
return kernel_selector::softmax_dim::Z;
|
||||
else
|
||||
return kernel_selector::softmax_dim::Y;
|
||||
case 3:
|
||||
if (rank > 4)
|
||||
return kernel_selector::softmax_dim::Y;
|
||||
else
|
||||
return kernel_selector::softmax_dim::X;
|
||||
case 4: return kernel_selector::softmax_dim::X;
|
||||
default: IE_THROW() << "Invalid softmax axis " << axis;
|
||||
}
|
||||
}
|
||||
|
||||
struct softmax_impl : typed_primitive_impl_ocl<softmax> {
|
||||
using parent = typed_primitive_impl_ocl<softmax>;
|
||||
using parent::parent;
|
||||
@@ -26,49 +48,10 @@ struct softmax_impl : typed_primitive_impl_ocl<softmax> {
|
||||
auto sm_optional_params =
|
||||
get_default_optional_params<kernel_selector::softmax_optional_params>(arg.get_program());
|
||||
|
||||
auto& input = sm_params.inputs[0];
|
||||
auto& output = sm_params.outputs[0];
|
||||
const auto primitive = arg.get_primitive();
|
||||
|
||||
switch (primitive->dimension) {
|
||||
case softmax::normalize_x:
|
||||
sm_params.dim = kernel_selector::softmax_dim::X;
|
||||
break;
|
||||
|
||||
case softmax::normalize_y:
|
||||
sm_params.dim = kernel_selector::softmax_dim::Y;
|
||||
break;
|
||||
|
||||
case softmax::normalize_fyx:
|
||||
// Flatten fused with softmax
|
||||
input = input.FlattenFeatureAndSpatials();
|
||||
output = output.FlattenFeatureAndSpatials();
|
||||
|
||||
sm_params.dim = kernel_selector::softmax_dim::FEATURE;
|
||||
break;
|
||||
|
||||
case softmax::normalize_b:
|
||||
sm_params.dim = kernel_selector::softmax_dim::BATCH;
|
||||
break;
|
||||
|
||||
case softmax::normalize_f:
|
||||
sm_params.dim = kernel_selector::softmax_dim::FEATURE;
|
||||
break;
|
||||
|
||||
case softmax::normalize_z:
|
||||
sm_params.dim = kernel_selector::softmax_dim::Z;
|
||||
break;
|
||||
|
||||
case softmax::normalize_all:
|
||||
input = input.FlattenEverything();
|
||||
output = output.FlattenEverything();
|
||||
|
||||
sm_params.dim = kernel_selector::softmax_dim::FEATURE;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw std::runtime_error("Wrong API - no such softmax");
|
||||
}
|
||||
size_t rank = arg.get_output_layout().get_rank();
|
||||
sm_params.dim = GetSoftmaxDim(primitive->dimension, rank);
|
||||
|
||||
auto& kernel_selector = kernel_selector::softmax_kernel_selector::Instance();
|
||||
auto best_kernels = kernel_selector.GetBestKernels(sm_params, sm_optional_params);
|
||||
|
||||
@@ -873,7 +873,7 @@ void program_node::init_onednn_primitive_attributes() {
|
||||
auto node = cldnn_post_ops[idx].node;
|
||||
|
||||
if (node->is_type<activation>()) {
|
||||
auto fused_desc = node->as<activation>().get_primitive();;
|
||||
auto fused_desc = node->as<activation>().get_primitive();
|
||||
if (fused_desc->activation_function == cldnn::activation_func::relu_negative_slope
|
||||
&& !fused_desc->additional_params_input.empty()) {
|
||||
auto dep_idx = cldnn_post_ops[idx].dep_start_idx;
|
||||
|
||||
@@ -31,6 +31,10 @@ std::string softmax_inst::to_string(softmax_node const& node) {
|
||||
|
||||
std::stringstream primitive_description;
|
||||
|
||||
json_composite softmax_info;
|
||||
softmax_info.add("dimension", desc->dimension);
|
||||
|
||||
node_info->add("softmax_info", softmax_info);
|
||||
node_info->dump(primitive_description);
|
||||
|
||||
return primitive_description.str();
|
||||
|
||||
@@ -27,8 +27,8 @@ KernelsPriority ExperimentalDetectronGenerateProposalsSingleImageRef::GetKernels
|
||||
}
|
||||
|
||||
bool ExperimentalDetectronGenerateProposalsSingleImageRef::Validate(const Params& p, const optional_params& o) const {
|
||||
if (p.GetType() != KernelType::EXPERIMENTAL_DETECTRON_GENERATE_PROPOSALS_SINGLE_IMAGE
|
||||
|| o.GetType() != KernelType::EXPERIMENTAL_DETECTRON_GENERATE_PROPOSALS_SINGLE_IMAGE) {
|
||||
if (p.GetType() != KernelType::EXPERIMENTAL_DETECTRON_GENERATE_PROPOSALS_SINGLE_IMAGE ||
|
||||
o.GetType() != KernelType::EXPERIMENTAL_DETECTRON_GENERATE_PROPOSALS_SINGLE_IMAGE) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -77,7 +77,7 @@ static inline std::vector<std::string> GetDefaultOrder(size_t size) {
|
||||
}
|
||||
|
||||
static inline std::string GetAxisName(size_t size, size_t axis) {
|
||||
std::vector<std::string> axis_names;;
|
||||
std::vector<std::string> axis_names;
|
||||
if (size <= 4) {
|
||||
axis_names = {"BATCH", "FEATURE", "Y", "X"};
|
||||
} else if (size == 5) {
|
||||
|
||||
@@ -19,7 +19,7 @@ KERNEL(convolution)(
|
||||
const uint group_x = (uint)get_group_id(0) * OUT_BLOCK_WIDTH;
|
||||
const uint group_y = (uint)get_group_id(1) * OUT_BLOCK_HEIGHT;
|
||||
const uint f = ((uint)get_group_id(2) * SIMD_SIZE * OUT_BLOCK_DEPTH) % OUTPUT_FEATURE_NUM;
|
||||
const uint b = ((uint)get_group_id(2) * SIMD_SIZE * OUT_BLOCK_DEPTH) / OUTPUT_FEATURE_NUM;;
|
||||
const uint b = ((uint)get_group_id(2) * SIMD_SIZE * OUT_BLOCK_DEPTH) / OUTPUT_FEATURE_NUM;
|
||||
|
||||
const uint ifm_part = get_sub_group_id();
|
||||
uint ifm_offset = ifm_part* OUT_BLOCK_DEPTH/2;
|
||||
@@ -167,10 +167,10 @@ KERNEL(convolution)(
|
||||
dotProd0[2 + OUT_BLOCK_WIDTH * (br + OUT_BLOCK_HEIGHT * bd)] += tmp[2];
|
||||
dotProd0[3 + OUT_BLOCK_WIDTH * (br + OUT_BLOCK_HEIGHT * bd)] += tmp[3];
|
||||
|
||||
dotProd0[0 + OUT_BLOCK_WIDTH * (br + OUT_BLOCK_HEIGHT * bd)] = ACTIVATION(dotProd0[0 + OUT_BLOCK_WIDTH * (br + OUT_BLOCK_HEIGHT * bd)], ACTIVATION_PARAMS);;
|
||||
dotProd0[1 + OUT_BLOCK_WIDTH * (br + OUT_BLOCK_HEIGHT * bd)] = ACTIVATION(dotProd0[1 + OUT_BLOCK_WIDTH * (br + OUT_BLOCK_HEIGHT * bd)], ACTIVATION_PARAMS);;
|
||||
dotProd0[2 + OUT_BLOCK_WIDTH * (br + OUT_BLOCK_HEIGHT * bd)] = ACTIVATION(dotProd0[2 + OUT_BLOCK_WIDTH * (br + OUT_BLOCK_HEIGHT * bd)], ACTIVATION_PARAMS);;
|
||||
dotProd0[3 + OUT_BLOCK_WIDTH * (br + OUT_BLOCK_HEIGHT * bd)] = ACTIVATION(dotProd0[3 + OUT_BLOCK_WIDTH * (br + OUT_BLOCK_HEIGHT * bd)], ACTIVATION_PARAMS);;
|
||||
dotProd0[0 + OUT_BLOCK_WIDTH * (br + OUT_BLOCK_HEIGHT * bd)] = ACTIVATION(dotProd0[0 + OUT_BLOCK_WIDTH * (br + OUT_BLOCK_HEIGHT * bd)], ACTIVATION_PARAMS);
|
||||
dotProd0[1 + OUT_BLOCK_WIDTH * (br + OUT_BLOCK_HEIGHT * bd)] = ACTIVATION(dotProd0[1 + OUT_BLOCK_WIDTH * (br + OUT_BLOCK_HEIGHT * bd)], ACTIVATION_PARAMS);
|
||||
dotProd0[2 + OUT_BLOCK_WIDTH * (br + OUT_BLOCK_HEIGHT * bd)] = ACTIVATION(dotProd0[2 + OUT_BLOCK_WIDTH * (br + OUT_BLOCK_HEIGHT * bd)], ACTIVATION_PARAMS);
|
||||
dotProd0[3 + OUT_BLOCK_WIDTH * (br + OUT_BLOCK_HEIGHT * bd)] = ACTIVATION(dotProd0[3 + OUT_BLOCK_WIDTH * (br + OUT_BLOCK_HEIGHT * bd)], ACTIVATION_PARAMS);
|
||||
|
||||
width_offset += 4;
|
||||
#endif
|
||||
@@ -178,7 +178,7 @@ KERNEL(convolution)(
|
||||
for(uint bc = width_offset; bc < OUT_BLOCK_WIDTH; bc++)
|
||||
{
|
||||
dotProd0[bc + OUT_BLOCK_WIDTH * (br + OUT_BLOCK_HEIGHT * bd)] += slm_vals[bc + OUT_BLOCK_WIDTH * (get_sub_group_local_id() + SIMD_SIZE * (br + OUT_BLOCK_HEIGHT * (bd + ifm_offset) ))];
|
||||
dotProd0[bc + OUT_BLOCK_WIDTH * (br + OUT_BLOCK_HEIGHT * bd)] = ACTIVATION(dotProd0[bc + OUT_BLOCK_WIDTH * (br + OUT_BLOCK_HEIGHT * bd)], ACTIVATION_PARAMS);;
|
||||
dotProd0[bc + OUT_BLOCK_WIDTH * (br + OUT_BLOCK_HEIGHT * bd)] = ACTIVATION(dotProd0[bc + OUT_BLOCK_WIDTH * (br + OUT_BLOCK_HEIGHT * bd)], ACTIVATION_PARAMS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,6 +66,6 @@ KERNEL (fully_connected_gpu_yxfn)(
|
||||
|
||||
output[output_idx] = res;
|
||||
#else
|
||||
output[output_idx] = ACTIVATION(result, ACTIVATION_PARAMS);;
|
||||
output[output_idx] = ACTIVATION(result, ACTIVATION_PARAMS);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -108,7 +108,7 @@ KERNEL(pooling_gpu_b_fs_yx_fsv4)(
|
||||
result[0] = FUNC_CALL(apply_pooling)(result[0], TO_ACCUMULATOR_TYPE(ch4_data[0]));
|
||||
result[1] = FUNC_CALL(apply_pooling)(result[1], TO_ACCUMULATOR_TYPE(ch4_data[1]));
|
||||
result[2] = FUNC_CALL(apply_pooling)(result[2], TO_ACCUMULATOR_TYPE(ch4_data[2]));
|
||||
result[3] = FUNC_CALL(apply_pooling)(result[3], TO_ACCUMULATOR_TYPE(ch4_data[3]));;
|
||||
result[3] = FUNC_CALL(apply_pooling)(result[3], TO_ACCUMULATOR_TYPE(ch4_data[3]));
|
||||
|
||||
input_idx += IN_X_PITCH;
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ KERNEL(reverse_ref)(
|
||||
#if INPUT0_DIMS >= 5
|
||||
else if (axis[i] == Z_INDEX) {
|
||||
printf("outputZ %d", OUTPUT_SIZE_Z);
|
||||
z = OUTPUT_SIZE_Z - z- 1;
|
||||
z = OUTPUT_SIZE_Z - z - 1;
|
||||
}
|
||||
#if INPUT0_DIMS == 6
|
||||
else if (axis[i] == W_INDEX) {
|
||||
|
||||
@@ -41,7 +41,7 @@ KERNEL(softmax)(
|
||||
ACCUMULATOR_TYPE denominator = 0.0;
|
||||
for (uint cls = 0; cls < INPUT0_CLASS_NUM; ++cls)
|
||||
{
|
||||
data[cls] = native_exp(data[cls] - max_value);;
|
||||
data[cls] = native_exp(data[cls] - max_value);
|
||||
denominator += data[cls];
|
||||
}
|
||||
|
||||
|
||||
@@ -14,34 +14,33 @@
|
||||
namespace ov {
|
||||
namespace intel_gpu {
|
||||
|
||||
static cldnn::softmax::dimension_t GetSoftmaxAxis(int64_t axis, size_t rank) {
|
||||
switch (axis) {
|
||||
case 0: return cldnn::softmax::normalize_b;
|
||||
case 1: return cldnn::softmax::normalize_f;
|
||||
case 2:
|
||||
if (rank > 4)
|
||||
return cldnn::softmax::normalize_z;
|
||||
else
|
||||
return cldnn::softmax::normalize_y;
|
||||
case 3:
|
||||
if (rank > 4)
|
||||
return cldnn::softmax::normalize_y;
|
||||
else
|
||||
return cldnn::softmax::normalize_x;
|
||||
case 4:
|
||||
return cldnn::softmax::normalize_x;
|
||||
default: IE_THROW() << "Invalid softmax axis " << axis;
|
||||
}
|
||||
return cldnn::softmax::normalize_fyx;
|
||||
}
|
||||
|
||||
static void CreateSoftmaxOp(Program& p, const std::shared_ptr<ngraph::op::v1::Softmax>& op) {
|
||||
p.ValidateInputs(op, {1});
|
||||
auto inputPrimitives = p.GetInputPrimitiveIDs(op);
|
||||
std::string layerName = layer_type_name_ID(op);
|
||||
auto softmaxPrim = cldnn::softmax(layerName,
|
||||
inputPrimitives[0],
|
||||
GetSoftmaxAxis(op->get_axis(), op->get_input_shape(0).size()),
|
||||
op->get_axis(),
|
||||
op->get_friendly_name());
|
||||
p.AddPrimitive(softmaxPrim);
|
||||
p.AddPrimitiveToProfiler(op);
|
||||
}
|
||||
|
||||
static void CreateSoftmaxOp(Program& p, const std::shared_ptr<ngraph::op::v8::Softmax>& op) {
|
||||
p.ValidateInputs(op, {1});
|
||||
auto inputPrimitives = p.GetInputPrimitiveIDs(op);
|
||||
std::string layerName = layer_type_name_ID(op);
|
||||
|
||||
int64_t axis = op->get_axis();
|
||||
size_t rank = op->get_input_shape(0).size();
|
||||
if (axis < 0)
|
||||
axis += rank;
|
||||
if (axis < 0 || axis >= static_cast<int64_t>(rank))
|
||||
IE_THROW() << "Softmax axis is not correspond to number of dimensions";
|
||||
|
||||
auto softmaxPrim = cldnn::softmax(layerName,
|
||||
inputPrimitives[0],
|
||||
axis,
|
||||
op->get_friendly_name());
|
||||
p.AddPrimitive(softmaxPrim);
|
||||
p.AddPrimitiveToProfiler(op);
|
||||
@@ -59,7 +58,7 @@ static void CreateLogSoftmaxOp(Program& p, const std::shared_ptr<ngraph::op::v5:
|
||||
|
||||
auto softmaxPrim = cldnn::softmax(layerNameSoftmax,
|
||||
inputPrimitives[0],
|
||||
GetSoftmaxAxis(static_cast<size_t>(axis), op->get_input_shape(0).size()),
|
||||
axis,
|
||||
op->get_friendly_name());
|
||||
|
||||
auto logPrim = cldnn::activation(layerName, layerNameSoftmax, cldnn::activation_func::log, {(0.0F), (0.0F)}, op->get_friendly_name());
|
||||
@@ -71,6 +70,7 @@ static void CreateLogSoftmaxOp(Program& p, const std::shared_ptr<ngraph::op::v5:
|
||||
}
|
||||
|
||||
REGISTER_FACTORY_IMPL(v1, Softmax);
|
||||
REGISTER_FACTORY_IMPL(v8, Softmax);
|
||||
REGISTER_FACTORY_IMPL(v5, LogSoftmax);
|
||||
|
||||
} // namespace intel_gpu
|
||||
|
||||
@@ -399,7 +399,7 @@ QueryNetworkResult Plugin::QueryNetwork(const CNNNetwork& network,
|
||||
auto ops = func->get_ordered_ops();
|
||||
|
||||
//Mark removed nodes as supported
|
||||
std::unordered_set<std::string> supported = GetRemovedNodes(function, func);;
|
||||
std::unordered_set<std::string> supported = GetRemovedNodes(function, func);
|
||||
std::unordered_set<std::string> unsupported;
|
||||
|
||||
std::unordered_set<std::string> supportedNotOriginal;
|
||||
@@ -599,7 +599,7 @@ Parameter Plugin::GetConfig(const std::string& name, const std::map<std::string,
|
||||
} else if (name == ov::num_streams) {
|
||||
return ov::util::from_string(val, ov::num_streams);
|
||||
} else if (name == ov::hint::num_requests) {
|
||||
auto temp = ov::util::from_string(val, ov::hint::num_requests);;
|
||||
auto temp = ov::util::from_string(val, ov::hint::num_requests);
|
||||
return temp;
|
||||
} else if (name == ov::device::id) {
|
||||
return ov::util::from_string(val, ov::device::id);
|
||||
|
||||
@@ -74,6 +74,7 @@
|
||||
#include <transformations/op_conversions/simplify_ctc_greedy_decoder_seq_len.hpp>
|
||||
#include "transformations/op_conversions/softmax_decomposition.hpp"
|
||||
#include <transformations/op_conversions/gelu7_downgrade.hpp>
|
||||
#include <transformations/op_conversions/convert_softmax_downgrade.hpp>
|
||||
#include <transformations/convert_precision.hpp>
|
||||
#include <transformations/init_node_info.hpp>
|
||||
#include <transformations/rt_info/fused_names_attribute.hpp>
|
||||
@@ -321,6 +322,7 @@ void TransformationsPipeline::apply(std::shared_ptr<ov::Model> func) {
|
||||
pass_config->disable<ngraph::pass::ConvertBroadcast3>();
|
||||
pass_config->disable<ngraph::pass::WeightsDequantizeToFakeQuantize>();
|
||||
pass_config->disable<ngraph::pass::SimplifyCTCGreedyDecoderSeqLen>();
|
||||
pass_config->disable<ngraph::pass::ConvertSoftMax8ToSoftMax1>();
|
||||
pass_config->enable<ngraph::pass::ConvertGather8ToGather7>();
|
||||
|
||||
if (!config.enable_loop_unrolling) {
|
||||
|
||||
@@ -22,7 +22,7 @@ struct softmax_test_params {
|
||||
tensor in_shape;
|
||||
data_types data_type;
|
||||
format input_format;
|
||||
softmax::dimension_t dimension;
|
||||
int64_t dimension;
|
||||
data_types default_type;
|
||||
format default_format;
|
||||
size_t expected_fused_primitives;
|
||||
@@ -65,13 +65,11 @@ public:
|
||||
/* ----------------------------------------------------------------------------------------------------- */
|
||||
/* ---------------------------------------- SoftMax cases ---------------------------------------------- */
|
||||
/* ----------------------------------------------------------------------------------------------------- */
|
||||
#define CASE_SOFTMAX_FP32_1 {1, 15, 4, 5}, data_types::f32, format::bfyx, softmax::dimension_t::normalize_f, data_types::f32, format::bfyx
|
||||
#define CASE_SOFTMAX_FP32_2 {1, 15, 4, 5}, data_types::f32, format::bfyx, softmax::dimension_t::normalize_x, data_types::f32, format::bfyx
|
||||
#define CASE_SOFTMAX_FP32_3 {1, 15, 4, 5}, data_types::f32, format::bfyx, softmax::dimension_t::normalize_fyx, data_types::f32, format::bfyx
|
||||
#define CASE_SOFTMAX_FP32_1 {1, 15, 4, 5}, data_types::f32, format::bfyx, 1, data_types::f32, format::bfyx
|
||||
#define CASE_SOFTMAX_FP32_2 {1, 15, 4, 5}, data_types::f32, format::bfyx, 3, data_types::f32, format::bfyx
|
||||
|
||||
#define CASE_SOFTMAX_FP16_1 {1, 15, 4, 5}, data_types::f16, format::bfyx, softmax::dimension_t::normalize_f, data_types::f16, format::bfyx
|
||||
#define CASE_SOFTMAX_FP16_2 {1, 15, 4, 5}, data_types::f16, format::bfyx, softmax::dimension_t::normalize_x, data_types::f16, format::bfyx
|
||||
#define CASE_SOFTMAX_FP16_3 {1, 15, 4, 5}, data_types::f16, format::bfyx, softmax::dimension_t::normalize_fyx, data_types::f16, format::bfyx
|
||||
#define CASE_SOFTMAX_FP16_1 {1, 15, 4, 5}, data_types::f16, format::bfyx, 1, data_types::f16, format::bfyx
|
||||
#define CASE_SOFTMAX_FP16_2 {1, 15, 4, 5}, data_types::f16, format::bfyx, 3, data_types::f16, format::bfyx
|
||||
|
||||
class softmax_quantize : public SoftmaxPrimitiveFusingTest {};
|
||||
TEST_P(softmax_quantize, basic) {
|
||||
@@ -94,11 +92,9 @@ INSTANTIATE_TEST_SUITE_P(fusings_gpu, softmax_quantize,
|
||||
::testing::ValuesIn(std::vector<softmax_test_params>{
|
||||
softmax_test_params{ CASE_SOFTMAX_FP32_1, 2, 3 },
|
||||
softmax_test_params{ CASE_SOFTMAX_FP32_2, 3, 3 },
|
||||
softmax_test_params{ CASE_SOFTMAX_FP32_3, 3, 3 },
|
||||
|
||||
softmax_test_params{ CASE_SOFTMAX_FP16_1, 2, 3 },
|
||||
softmax_test_params{ CASE_SOFTMAX_FP16_2, 3, 3 },
|
||||
softmax_test_params{ CASE_SOFTMAX_FP16_3, 3, 3 },
|
||||
}));
|
||||
|
||||
class softmax_quantize_fusing_through : public SoftmaxPrimitiveFusingTest {};
|
||||
|
||||
@@ -31,7 +31,7 @@ TEST(experimental_detectron_topk_rois_gpu_fp32, check_set_indices_layer) {
|
||||
{3, 1});
|
||||
|
||||
const std::string input_rois_id = "InputRois";
|
||||
const std::string input_indices_id = "InputIndices";;
|
||||
const std::string input_indices_id = "InputIndices";
|
||||
const std::string experimental_detectron_topk_rois_id = "experimental_detectron_topk_rois";
|
||||
topology topology;
|
||||
topology.add(input_layout(input_rois_id, roi_input->get_layout()));
|
||||
|
||||
@@ -1536,7 +1536,7 @@ TEST(reorder_gpu_opt, mean_mul)
|
||||
cldnn::mem_lock<float> ptr(output, get_test_stream());
|
||||
float* a_ptr = answers;
|
||||
for (auto& val : ptr)
|
||||
EXPECT_FLOAT_EQ(*(a_ptr++), val);;
|
||||
EXPECT_FLOAT_EQ(*(a_ptr++), val);
|
||||
|
||||
}
|
||||
|
||||
@@ -1571,7 +1571,7 @@ TEST(reorder_gpu_opt, mean_div)
|
||||
cldnn::mem_lock<float> ptr(output, get_test_stream());
|
||||
float* a_ptr = answers;
|
||||
for (auto& val : ptr)
|
||||
EXPECT_FLOAT_EQ(*(a_ptr++), val);;
|
||||
EXPECT_FLOAT_EQ(*(a_ptr++), val);
|
||||
|
||||
}
|
||||
|
||||
@@ -1602,7 +1602,7 @@ TEST(reorder_gpu_opt, mean_mul_val)
|
||||
cldnn::mem_lock<float> ptr(output, get_test_stream());
|
||||
float* a_ptr = answers;
|
||||
for (auto& val : ptr)
|
||||
EXPECT_FLOAT_EQ(*(a_ptr++), val);;
|
||||
EXPECT_FLOAT_EQ(*(a_ptr++), val);
|
||||
}
|
||||
|
||||
TEST(reorder_gpu_opt, mean_mul_val_float_to_int)
|
||||
|
||||
@@ -68,7 +68,7 @@ TEST_F(softmax_gpu_xb_f32_test_fixture, input_same_values) {
|
||||
|
||||
set_values(input, in_b);
|
||||
|
||||
network network(engine, topology(input_layout("input", input->get_layout()), softmax("softmax", "input")));
|
||||
network network(engine, topology(input_layout("input", input->get_layout()), softmax("softmax", "input", 3)));
|
||||
network.set_input_data("input", input);
|
||||
|
||||
auto outputs = network.execute();
|
||||
@@ -78,8 +78,7 @@ TEST_F(softmax_gpu_xb_f32_test_fixture, input_same_values) {
|
||||
auto output_prim = outputs.begin()->second.get_memory();
|
||||
|
||||
cldnn::mem_lock<float> output_ptr(output_prim, get_test_stream());
|
||||
for (uint32_t i = 0; i < out_size; i++)
|
||||
{
|
||||
for (uint32_t i = 0; i < out_size; i++) {
|
||||
out_buffer[i] = output_ptr[i];
|
||||
}
|
||||
compare_out_buffer_with_expected();
|
||||
@@ -98,7 +97,7 @@ TEST_F(softmax_gpu_xb_f32_test_fixture, input_same_values_batch_wise) {
|
||||
for(size_t i = 0; i < out_size; ++i)
|
||||
expected_buffer[i] = 0.1f;
|
||||
|
||||
network network(engine, topology(input_layout("input", input->get_layout()), softmax("softmax", "input")));
|
||||
network network(engine, topology(input_layout("input", input->get_layout()), softmax("softmax", "input", 3)));
|
||||
network.set_input_data("input", input);
|
||||
|
||||
auto outputs = network.execute();
|
||||
@@ -108,8 +107,7 @@ TEST_F(softmax_gpu_xb_f32_test_fixture, input_same_values_batch_wise) {
|
||||
auto output_prim = outputs.begin()->second.get_memory();
|
||||
|
||||
cldnn::mem_lock<float> output_ptr(output_prim, get_test_stream());
|
||||
for (uint32_t i = 0; i < out_size; i++)
|
||||
{
|
||||
for (uint32_t i = 0; i < out_size; i++) {
|
||||
out_buffer[i] = output_ptr[i];
|
||||
}
|
||||
compare_out_buffer_with_expected_batch_wise();
|
||||
@@ -153,7 +151,7 @@ TEST_F(softmax_gpu_xb_f32_test_fixture, values_batch_wise) {
|
||||
for(size_t i = 0; i < out_size; ++i)
|
||||
out_buffer[i] = NAN;
|
||||
|
||||
network network(engine, topology(input_layout("input", input->get_layout()), softmax("softmax", "input")));
|
||||
network network(engine, topology(input_layout("input", input->get_layout()), softmax("softmax", "input", 3)));
|
||||
network.set_input_data("input", input);
|
||||
|
||||
auto outputs = network.execute();
|
||||
@@ -163,96 +161,22 @@ TEST_F(softmax_gpu_xb_f32_test_fixture, values_batch_wise) {
|
||||
auto output_prim = outputs.begin()->second.get_memory();
|
||||
|
||||
cldnn::mem_lock<float> output_ptr(output_prim, get_test_stream());
|
||||
for (uint32_t i = 0; i < out_size; i++)
|
||||
{
|
||||
for (uint32_t i = 0; i < out_size; i++) {
|
||||
out_buffer[i] = output_ptr[i];
|
||||
}
|
||||
compare_out_buffer_with_expected_batch_wise();
|
||||
}
|
||||
|
||||
TEST(softmax_gpu_bfyx_f32, normalize_fyx) {
|
||||
// Input : 2x3x2x2
|
||||
static const int32_t x_size = 2, y_size = 2, feature_num = 3,
|
||||
batch_num = 2, buf_size = x_size*y_size * batch_num * feature_num;
|
||||
auto& engine = get_test_engine();
|
||||
|
||||
auto input = engine.allocate_memory({ data_types::f32, format::bfyx,{ batch_num, feature_num, x_size , y_size } });
|
||||
topology topology;
|
||||
topology.add(input_layout("input", input->get_layout()));
|
||||
topology.add(softmax("softmax", "input"));
|
||||
|
||||
set_values(input, { //bfyx
|
||||
//y0x0 y0x1 y1x0 y1x1
|
||||
/*b0f0*/0.1f, -0.1f, 0.9f, 1.5f,
|
||||
/*b0f1*/0.2f, 0.2f, -10.f, 5.2f,
|
||||
/*b1f2*/0.2f, 0.2f, -10.f, 5.2f,
|
||||
/*b1f0*/3.f, 0.5f, 7.f, 12.f,
|
||||
/*b1f1*/4.f, 0.5f, 8.f, 8.2f,
|
||||
/*b1f2*/0.2f, 0.2f, -10.f, 5.2f
|
||||
});
|
||||
|
||||
float expected_max_values[2] = {
|
||||
0.481618381f, 0.953259517f
|
||||
};
|
||||
|
||||
network network(engine, topology);
|
||||
|
||||
network.set_input_data("input", input);
|
||||
auto outputs = network.execute();
|
||||
|
||||
EXPECT_EQ(outputs.size(), size_t(1));
|
||||
EXPECT_EQ(outputs.begin()->first, "softmax");
|
||||
|
||||
auto output = outputs.at("softmax").get_memory();
|
||||
cldnn::mem_lock<float> output_ptr(output, get_test_stream());
|
||||
float out_buffer[buf_size];
|
||||
for (uint32_t i = 0; i < buf_size; i++)
|
||||
{
|
||||
out_buffer[i] = output_ptr[i];
|
||||
}
|
||||
|
||||
float sum = 0;
|
||||
float expected_sum = 1.0f;
|
||||
|
||||
float temp_max = 0;
|
||||
int max_value_buffer_index = 0;
|
||||
|
||||
for (uint32_t i = 0; i < batch_num; i++) //this for loops will sum results in a batch per feature, we expect that: sum = 1.0f
|
||||
{
|
||||
for (uint32_t j = 0; j < y_size; j++)
|
||||
{
|
||||
for (uint32_t k = 0; k < x_size; k++)
|
||||
{
|
||||
for (uint32_t l = 0; l < feature_num; l++)
|
||||
{
|
||||
int index = i * feature_num * x_size * y_size + j * x_size + k + l * x_size * y_size;
|
||||
sum += out_buffer[index];
|
||||
if (out_buffer[index] >= temp_max)
|
||||
{
|
||||
temp_max = out_buffer[index];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_EQ(true, are_equal(sum, expected_sum));
|
||||
sum = 0.0f;
|
||||
EXPECT_EQ(true, are_equal(temp_max, expected_max_values[max_value_buffer_index]));
|
||||
temp_max = 0;
|
||||
max_value_buffer_index++;
|
||||
}
|
||||
}
|
||||
|
||||
TEST(softmax_gpu_bfyx_f32, normalize_y) {
|
||||
// Input : 2x3x2x2
|
||||
static const int32_t x_size = 2, y_size = 2, feature_num = 3,
|
||||
batch_num = 2, buf_size = x_size*y_size * batch_num * feature_num;
|
||||
auto& engine = get_test_engine();
|
||||
|
||||
auto input = engine.allocate_memory({ data_types::f32, format::bfyx,{ batch_num, feature_num, x_size , y_size } });
|
||||
auto input = engine.allocate_memory({ data_types::f32, format::bfyx, { batch_num, feature_num, x_size, y_size } });
|
||||
topology topology;
|
||||
topology.add(input_layout("input", input->get_layout()));
|
||||
topology.add(softmax("softmax", "input", softmax::normalize_y));
|
||||
topology.add(softmax("softmax", "input", 2));
|
||||
|
||||
vector<float> input_vec = {
|
||||
//y0x0 y0x1 y1x0 y1x1
|
||||
@@ -297,33 +221,25 @@ TEST(softmax_gpu_bfyx_f32, normalize_y) {
|
||||
auto output = outputs.at("softmax").get_memory();
|
||||
cldnn::mem_lock<float> output_ptr(output, get_test_stream());
|
||||
float out_buffer[buf_size];
|
||||
for (uint32_t i = 0; i < buf_size; i++)
|
||||
{
|
||||
for (uint32_t i = 0; i < buf_size; i++) {
|
||||
out_buffer[i] = output_ptr[i];
|
||||
}
|
||||
|
||||
float temp_max = 0;
|
||||
float expected_sum = 1.0f;
|
||||
int max_value_buffer_index = 0;
|
||||
for (uint32_t i = 0; i < batch_num; i++) //this for loops will sum results in a batch per feature, we expect that: sum = 1.0f
|
||||
{
|
||||
for (uint32_t l = 0; l < feature_num; l++)
|
||||
{
|
||||
for (uint32_t k = 0; k < x_size; k++)
|
||||
{
|
||||
for (uint32_t i = 0; i < batch_num; i++) { //this for loops will sum results in a batch per feature, we expect that: sum = 1.0f
|
||||
for (uint32_t l = 0; l < feature_num; l++) {
|
||||
for (uint32_t k = 0; k < x_size; k++) {
|
||||
float sum = 0.0f;
|
||||
for (uint32_t j = 0; j < y_size; j++)
|
||||
{
|
||||
for (uint32_t j = 0; j < y_size; j++) {
|
||||
int index = i * feature_num * x_size * y_size +
|
||||
l * x_size * y_size +
|
||||
j * x_size +
|
||||
k;
|
||||
|
||||
if (out_buffer[index] >= temp_max)
|
||||
{
|
||||
l * x_size * y_size +
|
||||
j * x_size +
|
||||
k;
|
||||
if (out_buffer[index] >= temp_max) {
|
||||
temp_max = out_buffer[index];
|
||||
}
|
||||
|
||||
sum += out_buffer[index];
|
||||
}
|
||||
EXPECT_EQ(true, are_equal(temp_max, expected_max_values[max_value_buffer_index]));
|
||||
@@ -343,10 +259,10 @@ TEST(softmax_gpu_bfyx_f32, normalize_f) {
|
||||
batch_num = 2, buf_size = x_size*y_size * batch_num * feature_num;
|
||||
auto& engine = get_test_engine();
|
||||
|
||||
auto input = engine.allocate_memory({ data_types::f32, format::bfyx,{ batch_num, feature_num, x_size , y_size } });
|
||||
auto input = engine.allocate_memory({ data_types::f32, format::bfyx, { batch_num, feature_num, x_size, y_size } });
|
||||
topology topology;
|
||||
topology.add(input_layout("input", input->get_layout()));
|
||||
topology.add(softmax("softmax", "input", softmax::normalize_f));
|
||||
topology.add(softmax("softmax", "input", 1));
|
||||
|
||||
vector<float> input_vec = {
|
||||
//y0x0 y0x1 y1x0 y1x1
|
||||
@@ -385,33 +301,25 @@ TEST(softmax_gpu_bfyx_f32, normalize_f) {
|
||||
auto output = outputs.at("softmax").get_memory();
|
||||
cldnn::mem_lock<float> output_ptr(output, get_test_stream());
|
||||
float out_buffer[buf_size];
|
||||
for (uint32_t i = 0; i < buf_size; i++)
|
||||
{
|
||||
for (uint32_t i = 0; i < buf_size; i++) {
|
||||
out_buffer[i] = output_ptr[i];
|
||||
}
|
||||
|
||||
float temp_max = 0;
|
||||
float expected_sum = 1.0f;
|
||||
int max_value_buffer_index = 0;
|
||||
for (uint32_t i = 0; i < batch_num; i++) //this for loops will sum results in a batch per feature, we expect that: sum = 1.0f
|
||||
{
|
||||
for (uint32_t j = 0; j < y_size; j++)
|
||||
{
|
||||
for (uint32_t k = 0; k < x_size; k++)
|
||||
{
|
||||
for (uint32_t i = 0; i < batch_num; i++) { //this for loops will sum results in a batch per feature, we expect that: sum = 1.0f
|
||||
for (uint32_t j = 0; j < y_size; j++) {
|
||||
for (uint32_t k = 0; k < x_size; k++) {
|
||||
float sum = 0.0f;
|
||||
for (uint32_t l = 0; l < feature_num; l++)
|
||||
{
|
||||
for (uint32_t l = 0; l < feature_num; l++) {
|
||||
int index = i * feature_num * x_size * y_size +
|
||||
l * x_size * y_size +
|
||||
j * x_size +
|
||||
k;
|
||||
|
||||
if (out_buffer[index] >= temp_max)
|
||||
{
|
||||
l * x_size * y_size +
|
||||
j * x_size +
|
||||
k;
|
||||
if (out_buffer[index] >= temp_max) {
|
||||
temp_max = out_buffer[index];
|
||||
}
|
||||
|
||||
sum += out_buffer[index];
|
||||
}
|
||||
EXPECT_EQ(true, are_equal(temp_max, expected_max_values[max_value_buffer_index]));
|
||||
@@ -425,93 +333,16 @@ TEST(softmax_gpu_bfyx_f32, normalize_f) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST(softmax_gpu_yxfb_f32, normalize_f) {
|
||||
|
||||
static const int32_t x_size = 1, y_size = 2, feature_num = 1,
|
||||
batch_num = 12, buf_size = x_size*y_size * batch_num * feature_num;
|
||||
auto& engine = get_test_engine();
|
||||
|
||||
auto input = engine.allocate_memory({ data_types::f32, format::yxfb,{ batch_num, feature_num, y_size , x_size } });
|
||||
topology topology;
|
||||
topology.add(input_layout("input", input->get_layout()));
|
||||
topology.add(softmax("softmax", "input", softmax::normalize_fyx));
|
||||
|
||||
set_values(input, { //yxfb
|
||||
//f0b0 f0b1 f0b2 f0b3 f0b4 f0b5 f0b6 f0b7 f0b8 f0b9 f0b10 f0b11
|
||||
/*y0x0*/ 0.1f, -0.1f, 0.9f, 1.5f, 0.15f, -0.01f, 0.19f, 0.45f, 0.41f, -0.12f, 0.39f, 0.65f,
|
||||
/*y1x0*/ 0.2f, 0.2f, -10.f, 5.2f, 0.01f, 0.015f, 0.29f, 0.05f, 0.41f, -0.31f, 0.29f, 1.35f
|
||||
});
|
||||
|
||||
float expected_max_values[batch_num * feature_num * x_size] = {
|
||||
0.524979174f,
|
||||
0.574442506f,
|
||||
0.999981523f,
|
||||
0.975872993f,
|
||||
0.534942925f,
|
||||
0.506249666f,
|
||||
0.524979174f,
|
||||
0.598687649f,
|
||||
0.500000000f,
|
||||
0.547357619f,
|
||||
0.524979174f,
|
||||
0.668187797f
|
||||
};
|
||||
|
||||
network network(engine, topology);
|
||||
|
||||
network.set_input_data("input", input);
|
||||
auto outputs = network.execute();
|
||||
|
||||
EXPECT_EQ(outputs.size(), size_t(1));
|
||||
EXPECT_EQ(outputs.begin()->first, "softmax");
|
||||
|
||||
auto output = outputs.at("softmax").get_memory();
|
||||
cldnn::mem_lock<float> output_ptr(output, get_test_stream());
|
||||
float out_buffer[buf_size];
|
||||
for (uint32_t i = 0; i < buf_size; i++)
|
||||
{
|
||||
out_buffer[i] = output_ptr[i];
|
||||
}
|
||||
|
||||
float expected_sum = 1.0f;
|
||||
|
||||
float temp_max = 0;
|
||||
|
||||
for (uint32_t b = 0; b < batch_num; b++)
|
||||
{
|
||||
for (uint32_t f = 0; f < feature_num; f++)
|
||||
{
|
||||
for (uint32_t x = 0; x < x_size; x++)
|
||||
{
|
||||
float sum = 0.0f;
|
||||
for (uint32_t y = 0; y < y_size; y++)
|
||||
{
|
||||
int index = b + y * batch_num + f * feature_num + x * x_size;
|
||||
if (out_buffer[index] >= temp_max)
|
||||
{
|
||||
temp_max = out_buffer[index];
|
||||
}
|
||||
sum += out_buffer[index];
|
||||
}
|
||||
EXPECT_EQ(true, are_equal(temp_max, expected_max_values[b * feature_num * x_size + f * x_size + x]));
|
||||
temp_max = 0;
|
||||
EXPECT_EQ(true, are_equal(sum, expected_sum));
|
||||
sum = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(softmax_gpu_bfzyx_f32, normalize_z) {
|
||||
// Input : 2x3x2x2x2
|
||||
static const int32_t x_size = 2, y_size = 2, z_size = 2, feature_num = 3,
|
||||
batch_num = 2, buf_size = x_size *y_size * z_size * batch_num * feature_num;
|
||||
auto& engine = get_test_engine();
|
||||
|
||||
auto input = engine.allocate_memory({ data_types::f32, format::bfzyx,{ batch_num, feature_num, x_size , y_size, z_size } });
|
||||
auto input = engine.allocate_memory({ data_types::f32, format::bfzyx, { batch_num, feature_num, x_size, y_size, z_size } });
|
||||
topology topology;
|
||||
topology.add(input_layout("input", input->get_layout()));
|
||||
topology.add(softmax("softmax", "input", softmax::normalize_z));
|
||||
topology.add(softmax("softmax", "input", 2));
|
||||
|
||||
vector<float> input_vec = {
|
||||
// z0y0x0 z0y0x1 z0y1x0 z0y1x1 z1y0x0 z1y0x1 z1y1x0 z1y1x1
|
||||
@@ -551,36 +382,27 @@ TEST(softmax_gpu_bfzyx_f32, normalize_z) {
|
||||
auto output = outputs.at("softmax").get_memory();
|
||||
cldnn::mem_lock<float> output_ptr(output, get_test_stream());
|
||||
float out_buffer[buf_size];
|
||||
for (uint32_t i = 0; i < buf_size; i++)
|
||||
{
|
||||
for (uint32_t i = 0; i < buf_size; i++) {
|
||||
out_buffer[i] = output_ptr[i];
|
||||
}
|
||||
|
||||
float temp_max = 0;
|
||||
float expected_sum = 1.0f;
|
||||
int max_value_buffer_index = 0;
|
||||
for (uint32_t i = 0; i < batch_num; i++)
|
||||
{
|
||||
for (uint32_t l = 0; l < feature_num; l++)
|
||||
{
|
||||
for (uint32_t j = 0; j < y_size; j++)
|
||||
{
|
||||
for (uint32_t k = 0; k < x_size; k++)
|
||||
{
|
||||
for (uint32_t i = 0; i < batch_num; i++) {
|
||||
for (uint32_t l = 0; l < feature_num; l++) {
|
||||
for (uint32_t j = 0; j < y_size; j++) {
|
||||
for (uint32_t k = 0; k < x_size; k++) {
|
||||
float sum = 0.0f;
|
||||
for (uint32_t m = 0; m < z_size; m++)
|
||||
{
|
||||
for (uint32_t m = 0; m < z_size; m++) {
|
||||
int index = i * feature_num * x_size * y_size * z_size +
|
||||
l * x_size * y_size * z_size +
|
||||
m * x_size * y_size +
|
||||
j * x_size +
|
||||
k;
|
||||
|
||||
if (out_buffer[index] >= temp_max)
|
||||
{
|
||||
l * x_size * y_size * z_size +
|
||||
m * x_size * y_size +
|
||||
j * x_size +
|
||||
k;
|
||||
if (out_buffer[index] >= temp_max) {
|
||||
temp_max = out_buffer[index];
|
||||
}
|
||||
|
||||
sum += out_buffer[index];
|
||||
}
|
||||
EXPECT_EQ(true, are_equal(temp_max, expected_max_values[max_value_buffer_index]));
|
||||
@@ -594,242 +416,16 @@ TEST(softmax_gpu_bfzyx_f32, normalize_z) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST(softmax_gpu_bfyx_f32, normalize_all) {
|
||||
// Input : 2x3x2x2
|
||||
static const int32_t x_size = 2, y_size = 2, feature_num = 3,
|
||||
batch_num = 2, buf_size = x_size * y_size * batch_num * feature_num;
|
||||
auto& engine = get_test_engine();
|
||||
|
||||
auto input = engine.allocate_memory({data_types::f32, format::bfyx, {batch_num, feature_num, x_size, y_size}});
|
||||
topology topology;
|
||||
topology.add(input_layout("input", input->get_layout()));
|
||||
topology.add(softmax("softmax", "input", softmax::normalize_all));
|
||||
|
||||
set_values(input, {//bfyx
|
||||
// y0x0 y0x1 y1x0 y1x1
|
||||
/*b0f0*/ 0.1f, -0.1f, 0.9f, 1.5f,
|
||||
/*b0f1*/ 0.2f, 0.2f, -10.f, 5.2f,
|
||||
/*b0f2*/ 0.2f, 0.2f, -10.f, 5.2f,
|
||||
/*b1f0*/ 3.f, 0.5f, 7.f, 12.f,
|
||||
/*b1f1*/ 4.f, 0.5f, 8.f, 8.2f,
|
||||
/*b1f2*/ 0.2f, 0.2f, -10.f, 5.2f});
|
||||
|
||||
network network(engine, topology);
|
||||
|
||||
network.set_input_data("input", input);
|
||||
auto outputs = network.execute();
|
||||
|
||||
EXPECT_EQ(outputs.size(), size_t(1));
|
||||
EXPECT_EQ(outputs.begin()->first, "softmax");
|
||||
|
||||
auto output = outputs.at("softmax").get_memory();
|
||||
cldnn::mem_lock<float> output_ptr(output, get_test_stream());
|
||||
float sum = 0.0f;
|
||||
float expected_sum = 1.0f;
|
||||
for (uint32_t i = 0; i < buf_size; i++) {
|
||||
sum += output_ptr[i];
|
||||
}
|
||||
EXPECT_EQ(true, are_equal(sum, expected_sum));
|
||||
}
|
||||
|
||||
TEST(softmax_gpu_yxfb_f32, normalize_all) {
|
||||
// Input : 2x2x3x2
|
||||
static const int32_t x_size = 2, y_size = 2, feature_num = 3,
|
||||
batch_num = 2, buf_size = x_size * y_size * batch_num * feature_num;
|
||||
auto& engine = get_test_engine();
|
||||
|
||||
auto input = engine.allocate_memory({data_types::f32, format::yxfb, {y_size, x_size, feature_num, batch_num}});
|
||||
topology topology;
|
||||
topology.add(input_layout("input", input->get_layout()));
|
||||
topology.add(softmax("softmax", "input", softmax::normalize_all));
|
||||
|
||||
set_values(input, {//yxfb
|
||||
// f0b0 f0b1 f1b0 f1b1
|
||||
/*y0x0*/ 0.1f, -0.1f, 0.9f, 1.5f,
|
||||
/*y0x1*/ 0.2f, 0.2f, -10.f, 5.2f,
|
||||
/*y0x2*/ 0.2f, 0.2f, -10.f, 5.2f,
|
||||
/*y1x0*/ 3.f, 0.5f, 7.f, 12.f,
|
||||
/*y1x1*/ 4.f, 0.5f, 8.f, 8.2f,
|
||||
/*y1x2*/ 0.2f, 0.2f, -10.f, 5.2f});
|
||||
|
||||
network network(engine, topology);
|
||||
|
||||
network.set_input_data("input", input);
|
||||
auto outputs = network.execute();
|
||||
|
||||
EXPECT_EQ(outputs.size(), size_t(1));
|
||||
EXPECT_EQ(outputs.begin()->first, "softmax");
|
||||
|
||||
auto output = outputs.at("softmax").get_memory();
|
||||
cldnn::mem_lock<float> output_ptr(output, get_test_stream());
|
||||
float sum = 0.0f;
|
||||
float expected_sum = 1.0f;
|
||||
for (uint32_t i = 0; i < buf_size; i++) {
|
||||
sum += output_ptr[i];
|
||||
}
|
||||
EXPECT_EQ(true, are_equal(sum, expected_sum));
|
||||
}
|
||||
|
||||
TEST(softmax_gpu_bfzyx_f32, normalize_all) {
|
||||
// Input : 2x3x2x2x2
|
||||
static const int32_t x_size = 2, y_size = 2, z_size = 2, feature_num = 3,
|
||||
batch_num = 2, buf_size = x_size * y_size * z_size * batch_num * feature_num;
|
||||
auto& engine = get_test_engine();
|
||||
|
||||
auto input = engine.allocate_memory({data_types::f32, format::bfzyx, {batch_num, feature_num, x_size, y_size, z_size}});
|
||||
topology topology;
|
||||
topology.add(input_layout("input", input->get_layout()));
|
||||
topology.add(softmax("softmax", "input", softmax::normalize_all));
|
||||
|
||||
set_values(input, {// z0y0x0 z0y0x1 z0y1x0 z0y1x1 z1y0x0 z1y0x1 z1y1x0 z1y1x1
|
||||
/*b0f0*/ 0.1f, -0.1f, 0.9f, 1.5f, 0.2f, -0.2f, 0.9f, 2.5f,
|
||||
/*b0f1*/ 0.2f, 0.2f, -10.f, 5.2f, 0.3f, 0.1f, -11.f, 6.2f,
|
||||
/*b0f2*/ 0.2f, 0.2f, -10.f, 5.2f, 0.1f, 0.3f, -9.f, 4.2f,
|
||||
|
||||
/*b1f0*/ 3.f, 0.5f, 7.f, 12.f, 5.f, 0.1f, 6.f, 22.f,
|
||||
/*b1f1*/ 4.f, 0.5f, 8.f, 8.2f, 2.2f, 0.3f, 6.f, 5.2f,
|
||||
/*b1f2*/ 0.2f, 0.2f, -10.f, 5.2f, 1.2f, 0.3f, -12.f, 2.2f});
|
||||
network network(engine, topology);
|
||||
|
||||
network.set_input_data("input", input);
|
||||
auto outputs = network.execute();
|
||||
|
||||
EXPECT_EQ(outputs.size(), size_t(1));
|
||||
EXPECT_EQ(outputs.begin()->first, "softmax");
|
||||
|
||||
auto output = outputs.at("softmax").get_memory();
|
||||
cldnn::mem_lock<float> output_ptr(output, get_test_stream());
|
||||
float sum = 0.0f;
|
||||
float expected_sum = 1.0f;
|
||||
for (uint32_t i = 0; i < buf_size; i++) {
|
||||
sum += output_ptr[i];
|
||||
}
|
||||
EXPECT_EQ(true, are_equal(sum, expected_sum));
|
||||
}
|
||||
|
||||
TEST(softmax_gpu_bfyx_f16, normalize_all) {
|
||||
// Input : 2x3x2x2
|
||||
static const int32_t x_size = 2, y_size = 2, feature_num = 3,
|
||||
batch_num = 2, buf_size = x_size * y_size * batch_num * feature_num;
|
||||
auto& engine = get_test_engine();
|
||||
|
||||
auto input = engine.allocate_memory({data_types::f16, format::bfyx, {batch_num, feature_num, x_size, y_size}});
|
||||
topology topology;
|
||||
topology.add(input_layout("input", input->get_layout()));
|
||||
topology.add(softmax("softmax", "input", softmax::normalize_all));
|
||||
|
||||
set_values(input, {//bfyx
|
||||
// y0x0 y0x1 y1x0 y1x1
|
||||
/*b0f0*/ FLOAT16(0.1f), FLOAT16(-0.1f), FLOAT16(0.9f), FLOAT16(1.5f),
|
||||
/*b0f1*/ FLOAT16(0.2f), FLOAT16(0.2f), FLOAT16(-10.f), FLOAT16(5.2f),
|
||||
/*b0f2*/ FLOAT16(0.2f), FLOAT16(0.2f), FLOAT16(-10.f), FLOAT16(5.2f),
|
||||
/*b1f0*/ FLOAT16(3.f), FLOAT16(0.5f), FLOAT16(7.f), FLOAT16(12.f),
|
||||
/*b1f1*/ FLOAT16(4.f), FLOAT16(0.5f), FLOAT16(8.f), FLOAT16(8.2f),
|
||||
/*b1f2*/ FLOAT16(0.2f), FLOAT16(0.2f), FLOAT16(-10.f), FLOAT16(5.2f)});
|
||||
|
||||
network network(engine, topology);
|
||||
|
||||
network.set_input_data("input", input);
|
||||
auto outputs = network.execute();
|
||||
|
||||
EXPECT_EQ(outputs.size(), size_t(1));
|
||||
EXPECT_EQ(outputs.begin()->first, "softmax");
|
||||
|
||||
auto output = outputs.at("softmax").get_memory();
|
||||
cldnn::mem_lock<uint16_t> output_ptr(output, get_test_stream());
|
||||
float sum = 0.0f;
|
||||
float expected_sum = 1.0f;
|
||||
for (uint32_t i = 0; i < buf_size; i++) {
|
||||
sum += float16_to_float32(output_ptr[i]);
|
||||
}
|
||||
ASSERT_NEAR(sum, expected_sum, 0.001);
|
||||
}
|
||||
|
||||
TEST(softmax_gpu_yxfb_f16, normalize_all) {
|
||||
// Input : 2x2x3x2
|
||||
static const int32_t x_size = 2, y_size = 2, feature_num = 3,
|
||||
batch_num = 2, buf_size = x_size * y_size * batch_num * feature_num;
|
||||
auto& engine = get_test_engine();
|
||||
|
||||
auto input = engine.allocate_memory({data_types::f16, format::yxfb, {y_size, x_size, feature_num, batch_num}});
|
||||
topology topology;
|
||||
topology.add(input_layout("input", input->get_layout()));
|
||||
topology.add(softmax("softmax", "input", softmax::normalize_all));
|
||||
|
||||
set_values(input, {//yxfb
|
||||
// f0b0 f0b1 f1b0 f1b1
|
||||
/*y0x0*/ FLOAT16(0.1f), FLOAT16(-0.1f), FLOAT16(0.9f), FLOAT16(1.5f),
|
||||
/*y0x1*/ FLOAT16(0.2f), FLOAT16(0.2f), FLOAT16(-10.f), FLOAT16(5.2f),
|
||||
/*y0x2*/ FLOAT16(0.2f), FLOAT16(0.2f), FLOAT16(-10.f), FLOAT16(5.2f),
|
||||
/*y1x0*/ FLOAT16(3.f), FLOAT16(0.5f), FLOAT16(7.f), FLOAT16(12.f),
|
||||
/*y1x1*/ FLOAT16(4.f), FLOAT16(0.5f), FLOAT16(8.f), FLOAT16(8.2f),
|
||||
/*y1x2*/ FLOAT16(0.2f), FLOAT16(0.2f), FLOAT16(-10.f), FLOAT16(5.2f)});
|
||||
|
||||
network network(engine, topology);
|
||||
|
||||
network.set_input_data("input", input);
|
||||
auto outputs = network.execute();
|
||||
|
||||
EXPECT_EQ(outputs.size(), size_t(1));
|
||||
EXPECT_EQ(outputs.begin()->first, "softmax");
|
||||
|
||||
auto output = outputs.at("softmax").get_memory();
|
||||
cldnn::mem_lock<uint16_t> output_ptr(output, get_test_stream());
|
||||
float sum = 0.0f;
|
||||
float expected_sum = 1.0f;
|
||||
for (uint32_t i = 0; i < buf_size; i++) {
|
||||
sum += float16_to_float32(output_ptr[i]);
|
||||
}
|
||||
ASSERT_NEAR(sum, expected_sum, 0.001);
|
||||
}
|
||||
|
||||
TEST(softmax_gpu_bfzyx_f16, normalize_all) {
|
||||
// Input : 2x3x2x2x2
|
||||
static const int32_t x_size = 2, y_size = 2, z_size = 2, feature_num = 3,
|
||||
batch_num = 2, buf_size = x_size * y_size * z_size * batch_num * feature_num;
|
||||
auto& engine = get_test_engine();
|
||||
|
||||
auto input = engine.allocate_memory({data_types::f16, format::bfzyx, {batch_num, feature_num, x_size, y_size, z_size}});
|
||||
topology topology;
|
||||
topology.add(input_layout("input", input->get_layout()));
|
||||
topology.add(softmax("softmax", "input", softmax::normalize_all));
|
||||
|
||||
set_values(input, {// z0y0x0 z0y0x1 z0y1x0 z0y1x1 z1y0x0 z1y0x1 z1y1x0 z1y1x1
|
||||
/*b0f0*/ FLOAT16(0.1f), FLOAT16(-0.1f), FLOAT16(0.9f), FLOAT16(1.5f), FLOAT16(0.2f), FLOAT16(-0.2f), FLOAT16(0.9f), FLOAT16(2.5f),
|
||||
/*b0f1*/ FLOAT16(0.2f), FLOAT16(0.2f), FLOAT16(-10.f), FLOAT16(5.2f), FLOAT16(0.3f), FLOAT16(0.1f), FLOAT16(-11.f), FLOAT16(6.2f),
|
||||
/*b0f2*/ FLOAT16(0.2f), FLOAT16(0.2f), FLOAT16(-10.f), FLOAT16(5.2f), FLOAT16(0.1f), FLOAT16(0.3f), FLOAT16(-9.f), FLOAT16(4.2f),
|
||||
|
||||
/*b1f0*/ FLOAT16(3.f), FLOAT16(0.5f), FLOAT16(7.f), FLOAT16(12.f), FLOAT16(5.f), FLOAT16(0.1f), FLOAT16(6.f), FLOAT16(22.f),
|
||||
/*b1f1*/ FLOAT16(4.f), FLOAT16(0.5f), FLOAT16(8.f), FLOAT16(8.2f), FLOAT16(2.2f), FLOAT16(0.3f), FLOAT16(6.f), FLOAT16(5.2f),
|
||||
/*b1f2*/ FLOAT16(0.2f), FLOAT16(0.2f), FLOAT16(-10.f), FLOAT16(5.2f), FLOAT16(1.2f), FLOAT16(0.3f), FLOAT16(-12.f), FLOAT16(2.2f)});
|
||||
network network(engine, topology);
|
||||
|
||||
network.set_input_data("input", input);
|
||||
auto outputs = network.execute();
|
||||
|
||||
EXPECT_EQ(outputs.size(), size_t(1));
|
||||
EXPECT_EQ(outputs.begin()->first, "softmax");
|
||||
|
||||
auto output = outputs.at("softmax").get_memory();
|
||||
cldnn::mem_lock<uint16_t> output_ptr(output, get_test_stream());
|
||||
float sum = 0.0f;
|
||||
float expected_sum = 1.0f;
|
||||
for (uint32_t i = 0; i < buf_size; i++) {
|
||||
sum += float16_to_float32(output_ptr[i]);
|
||||
}
|
||||
ASSERT_NEAR(sum, expected_sum, 0.001);
|
||||
}
|
||||
|
||||
TEST(softmax_gpu_bfyx_f32, normalize_b) {
|
||||
// Input : 3x2x2x2
|
||||
static const int32_t x_size = 2, y_size = 2, feature_num = 2,
|
||||
batch_num = 3, buf_size = x_size*y_size * batch_num * feature_num;
|
||||
auto& engine = get_test_engine();
|
||||
|
||||
auto input = engine.allocate_memory({ data_types::f32, format::bfyx,{ batch_num, feature_num, x_size , y_size } });
|
||||
auto input = engine.allocate_memory({ data_types::f32, format::bfyx, { batch_num, feature_num, x_size, y_size } });
|
||||
topology topology;
|
||||
topology.add(input_layout("input", input->get_layout()));
|
||||
topology.add(softmax("softmax", "input", softmax::normalize_b));
|
||||
topology.add(softmax("softmax", "input", 0));
|
||||
|
||||
vector<float> input_vec = {
|
||||
// y0x0 y0x1 y1x0 y1x1
|
||||
@@ -869,33 +465,25 @@ TEST(softmax_gpu_bfyx_f32, normalize_b) {
|
||||
auto output = outputs.at("softmax").get_memory();
|
||||
cldnn::mem_lock<float> output_ptr(output, get_test_stream());
|
||||
float out_buffer[buf_size];
|
||||
for (uint32_t i = 0; i < buf_size; i++)
|
||||
{
|
||||
for (uint32_t i = 0; i < buf_size; i++) {
|
||||
out_buffer[i] = output_ptr[i];
|
||||
}
|
||||
|
||||
float temp_max = 0;
|
||||
float expected_sum = 1.0f;
|
||||
int max_value_buffer_index = 0;
|
||||
for (uint32_t i = 0; i < feature_num; i++) //this for loops will sum results in a batch per feature, we expect that: sum = 1.0f
|
||||
{
|
||||
for (uint32_t j = 0; j < y_size; j++)
|
||||
{
|
||||
for (uint32_t k = 0; k < x_size; k++)
|
||||
{
|
||||
for (uint32_t i = 0; i < feature_num; i++) { //this for loops will sum results in a batch per feature, we expect that: sum = 1.0f
|
||||
for (uint32_t j = 0; j < y_size; j++) {
|
||||
for (uint32_t k = 0; k < x_size; k++) {
|
||||
float sum = 0.0f;
|
||||
for (uint32_t l = 0; l < batch_num; l++)
|
||||
{
|
||||
for (uint32_t l = 0; l < batch_num; l++) {
|
||||
int index = l * feature_num * x_size * y_size +
|
||||
i * x_size * y_size +
|
||||
j * x_size +
|
||||
k;
|
||||
|
||||
if (out_buffer[index] >= temp_max)
|
||||
{
|
||||
if (out_buffer[index] >= temp_max) {
|
||||
temp_max = out_buffer[index];
|
||||
}
|
||||
|
||||
sum += out_buffer[index];
|
||||
}
|
||||
EXPECT_EQ(true, are_equal(temp_max, expected_max_values[max_value_buffer_index]));
|
||||
@@ -932,24 +520,19 @@ class softmax_test : public tests::generic_test
|
||||
{
|
||||
|
||||
public:
|
||||
softmax_test() : tests::generic_test()
|
||||
{
|
||||
}
|
||||
softmax_test() : tests::generic_test() {}
|
||||
|
||||
void SetUp() override
|
||||
{
|
||||
void SetUp() override {
|
||||
max_ulps_diff_allowed = 6;
|
||||
}
|
||||
|
||||
static void TearDownTestCase()
|
||||
{
|
||||
static void TearDownTestCase() {
|
||||
all_layer_params.clear();
|
||||
all_generic_params.clear();
|
||||
}
|
||||
|
||||
static std::vector<std::shared_ptr<cldnn::primitive>> generate_specific_test_params()
|
||||
{
|
||||
all_layer_params.emplace_back(new softmax("softmax", "input0", softmax::normalize_f));
|
||||
static std::vector<std::shared_ptr<cldnn::primitive>> generate_specific_test_params() {
|
||||
all_layer_params.emplace_back(new softmax("softmax", "input0", 1));
|
||||
|
||||
//The test checks only valid combinations.
|
||||
//TODO: add more combinations.
|
||||
@@ -957,21 +540,18 @@ public:
|
||||
return all_layer_params;
|
||||
}
|
||||
|
||||
static std::vector<std::shared_ptr<tests::test_params>> generate_generic_test_params()
|
||||
{
|
||||
static std::vector<std::shared_ptr<tests::test_params>> generate_generic_test_params() {
|
||||
return generic_test::generate_generic_test_params(all_generic_params);
|
||||
}
|
||||
|
||||
bool is_format_supported(cldnn::format format) override
|
||||
{
|
||||
bool is_format_supported(cldnn::format format) override {
|
||||
return
|
||||
format == cldnn::format::yxfb ||
|
||||
format == cldnn::format::bfyx;
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
memory::ptr generate_reference_typed(const std::vector<memory::ptr> & inputs)
|
||||
{
|
||||
memory::ptr generate_reference_typed(const std::vector<memory::ptr>& inputs) {
|
||||
assert(inputs.size() == 1);
|
||||
const memory::ptr input = inputs[0];
|
||||
|
||||
@@ -1003,12 +583,10 @@ public:
|
||||
|
||||
for (int n = 0; n < in0_b; ++n)
|
||||
for (int y = 0; y < in0_h; ++y)
|
||||
for (int x = 0; x < in0_w; ++x)
|
||||
{
|
||||
for (int x = 0; x < in0_w; ++x) {
|
||||
float max_val = -std::numeric_limits<float>::infinity();
|
||||
|
||||
for (int c = 0; c < in0_f; ++c)
|
||||
{
|
||||
for (int c = 0; c < in0_f; ++c) {
|
||||
const size_t in0_idx = get_linear_index(input->get_layout(), n, c, y, x, input_desc);
|
||||
|
||||
max_val = std::max(max_val, static_cast<float>(in0_mem[in0_idx]));
|
||||
@@ -1016,8 +594,7 @@ public:
|
||||
|
||||
float Z = 0;
|
||||
|
||||
for (int c = 0; c < in0_f; ++c)
|
||||
{
|
||||
for (int c = 0; c < in0_f; ++c) {
|
||||
const size_t in0_idx = get_linear_index(input->get_layout(), n, c, y, x, input_desc);
|
||||
|
||||
float tmp = static_cast<float>((Type)std::exp(static_cast<float>(in0_mem[in0_idx]) - max_val));
|
||||
@@ -1025,8 +602,7 @@ public:
|
||||
cached_exp_vals[c] = tmp;
|
||||
}
|
||||
|
||||
for (int c = 0; c < in0_f; ++c)
|
||||
{
|
||||
for (int c = 0; c < in0_f; ++c) {
|
||||
const size_t out_idx = get_linear_index(output->get_layout(), n, c, y, x, input_desc);
|
||||
out_mem[out_idx] = (Type)(cached_exp_vals[c] / Z);
|
||||
}
|
||||
@@ -1035,23 +611,18 @@ public:
|
||||
return output;
|
||||
}
|
||||
|
||||
virtual memory::ptr generate_reference(const std::vector<memory::ptr> & inputs) override
|
||||
{
|
||||
if (generic_params->data_type == data_types::f32)
|
||||
{
|
||||
virtual memory::ptr generate_reference(const std::vector<memory::ptr>& inputs) override {
|
||||
if (generic_params->data_type == data_types::f32) {
|
||||
return generate_reference_typed<float>(inputs);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
return generate_reference_typed<FLOAT16>(inputs);
|
||||
}
|
||||
}
|
||||
|
||||
static std::string custom_param_name(const ::testing::TestParamInfo<std::tuple<std::shared_ptr<tests::test_params>, std::shared_ptr<cldnn::primitive>>>& info)
|
||||
{
|
||||
static std::string custom_param_name(const ::testing::TestParamInfo<std::tuple<std::shared_ptr<tests::test_params>, std::shared_ptr<cldnn::primitive>>>& info) {
|
||||
std::stringstream res;
|
||||
|
||||
const auto & p = std::get<0>(info.param);
|
||||
const auto& p = std::get<0>(info.param);
|
||||
|
||||
assert (p->data_type == data_types::f32 ||
|
||||
p->data_type == data_types::f16);
|
||||
@@ -1059,13 +630,11 @@ public:
|
||||
res << info.index
|
||||
<< "_" << (p->data_type == data_types::f32 ? "f32" : "f16");
|
||||
|
||||
for (unsigned i = 0; i < p->input_layouts.size(); ++i)
|
||||
{
|
||||
for (unsigned i = 0; i < p->input_layouts.size(); ++i) {
|
||||
const auto chans = format::traits(p->fmt).order;
|
||||
|
||||
res << "_" << "Input" << i;
|
||||
for (unsigned int j = 0; j < p->input_layouts[i].get_tensor().sizes(p->fmt).size(); ++j)
|
||||
{
|
||||
for (unsigned int j = 0; j < p->input_layouts[i].get_tensor().sizes(p->fmt).size(); ++j) {
|
||||
res << chans[j] << p->input_layouts[i].get_tensor().sizes(p->fmt)[j];
|
||||
}
|
||||
}
|
||||
@@ -1074,17 +643,14 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
static std::vector<std::shared_ptr<tests::test_params>> all_generic_params;
|
||||
static std::vector<std::shared_ptr<cldnn::primitive>> all_layer_params;
|
||||
|
||||
};
|
||||
|
||||
std::vector<std::shared_ptr<cldnn::primitive>> softmax_test::all_layer_params = {};
|
||||
std::vector<std::shared_ptr<tests::test_params>> softmax_test::all_generic_params = {};
|
||||
|
||||
TEST_P(softmax_test, SOFTMAX)
|
||||
{
|
||||
TEST_P(softmax_test, SOFTMAX) {
|
||||
run_single_test();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user