[GPU] reorder_data supports fusing two or more activations (#23306)
### Details: - *Currently reorder_data supports fusing only one activation* - *reorder_data should be able to fuse two or more activations* ### Tickets: - *132988*
This commit is contained in:
parent
d0c20f7714
commit
14bc4222a8
|
|
@ -137,42 +137,81 @@ KERNEL (reorder_data)(
|
|||
#endif
|
||||
|
||||
#if defined INPUT0_LAYOUT_NV12 && !SURFACE_INPUT
|
||||
uint8 ov = RESHAPE_DIMS(INPUT0, OUTPUT, b, 0, v, u, w, z, y, x);
|
||||
uint output_idx = FUNC_CALL(get_output_index)(OPTIONAL_SHAPE_INFO_TENSOR ov.s0, ov.s1, ov.s2, ov.s3, ov.s4, ov.s5, ov.s6, ov.s7);
|
||||
output[output_idx] = ACTIVATION_FUNC_TYPED(OUTPUT_REORDER, TO_OUTPUT_REORDER_TYPE(R), NL_M, NL_N);
|
||||
ov = RESHAPE_DIMS(INPUT0, OUTPUT, b, 1, v, u, w, z, y, x);
|
||||
output_idx = FUNC_CALL(get_output_index)(OPTIONAL_SHAPE_INFO_TENSOR ov.s0, ov.s1, ov.s2, ov.s3, ov.s4, ov.s5, ov.s6, ov.s7);
|
||||
output[output_idx] = ACTIVATION_FUNC_TYPED(OUTPUT_REORDER, TO_OUTPUT_REORDER_TYPE(G), NL_M, NL_N);
|
||||
ov = RESHAPE_DIMS(INPUT0, OUTPUT, b, 2, v, u, w, z, y, x);
|
||||
output_idx = FUNC_CALL(get_output_index)(OPTIONAL_SHAPE_INFO_TENSOR ov.s0, ov.s1, ov.s2, ov.s3, ov.s4, ov.s5, ov.s6, ov.s7);
|
||||
output[output_idx] = ACTIVATION_FUNC_TYPED(OUTPUT_REORDER, TO_OUTPUT_REORDER_TYPE(B), NL_M, NL_N);
|
||||
uint8 ov0 = RESHAPE_DIMS(INPUT0, OUTPUT, b, 0, v, u, w, z, y, x);
|
||||
uint8 ov1 = RESHAPE_DIMS(INPUT0, OUTPUT, b, 1, v, u, w, z, y, x);
|
||||
uint8 ov2 = RESHAPE_DIMS(INPUT0, OUTPUT, b, 2, v, u, w, z, y, x);
|
||||
uint output_idx_R = FUNC_CALL(get_output_index)(OPTIONAL_SHAPE_INFO_TENSOR ov0.s0, ov0.s1, ov0.s2, ov0.s3, ov0.s4, ov0.s5, ov0.s6, ov0.s7);
|
||||
uint output_idx_G = FUNC_CALL(get_output_index)(OPTIONAL_SHAPE_INFO_TENSOR ov1.s0, ov1.s1, ov1.s2, ov1.s3, ov1.s4, ov1.s5, ov1.s6, ov1.s7);
|
||||
uint output_idx_B = FUNC_CALL(get_output_index)(OPTIONAL_SHAPE_INFO_TENSOR ov2.s0, ov2.s1, ov2.s2, ov2.s3, ov2.s4, ov2.s5, ov2.s6, ov2.s7);
|
||||
#if HAS_FUSED_OPS
|
||||
res = TO_OUTPUT_REORDER_TYPE(R);
|
||||
FUSED_OPS;
|
||||
output[output_idx_R] = FUSED_OPS_RESULT;
|
||||
res = TO_OUTPUT_REORDER_TYPE(G);
|
||||
FUSED_OPS;
|
||||
output[output_idx_G] = FUSED_OPS_RESULT;
|
||||
res = TO_OUTPUT_REORDER_TYPE(B);
|
||||
FUSED_OPS;
|
||||
output[output_idx_B] = FUSED_OPS_RESULT;
|
||||
#else
|
||||
output[output_idx_R] = ACTIVATION_FUNC_TYPED(OUTPUT_REORDER, TO_OUTPUT_REORDER_TYPE(R), NL_M, NL_N);
|
||||
output[output_idx_G] = ACTIVATION_FUNC_TYPED(OUTPUT_REORDER, TO_OUTPUT_REORDER_TYPE(G), NL_M, NL_N);
|
||||
output[output_idx_B] = ACTIVATION_FUNC_TYPED(OUTPUT_REORDER, TO_OUTPUT_REORDER_TYPE(B), NL_M, NL_N);
|
||||
#endif
|
||||
#elif INPUT0_LAYOUT_IMAGE_2D_RGBA
|
||||
uint8 ov = RESHAPE_DIMS(INPUT0, OUTPUT, b, 0, v, u, w, z, y, x);
|
||||
uint output_idx = FUNC_CALL(get_output_index)(OPTIONAL_SHAPE_INFO_TENSOR ov.s0, ov.s1, ov.s2, ov.s3, ov.s4, ov.s5, ov.s6, ov.s7);
|
||||
output[output_idx] = ACTIVATION_FUNC_TYPED(OUTPUT_REORDER, TO_OUTPUT_REORDER_TYPE(colorRGBA.s0), NL_M, NL_N);
|
||||
ov = RESHAPE_DIMS(INPUT0, OUTPUT, b, 1, v, u, w, z, y, x);
|
||||
output_idx = FUNC_CALL(get_output_index)(OPTIONAL_SHAPE_INFO_TENSOR ov.s0, ov.s1, ov.s2, ov.s3, ov.s4, ov.s5, ov.s6, ov.s7);
|
||||
output[output_idx] = ACTIVATION_FUNC_TYPED(OUTPUT_REORDER, TO_OUTPUT_REORDER_TYPE(colorRGBA.s1), NL_M, NL_N);
|
||||
ov = RESHAPE_DIMS(INPUT0, OUTPUT, b, 2, v, u, w, z, y, x);
|
||||
output_idx = FUNC_CALL(get_output_index)(OPTIONAL_SHAPE_INFO_TENSOR ov.s0, ov.s1, ov.s2, ov.s3, ov.s4, ov.s5, ov.s6, ov.s7);
|
||||
output[output_idx] = ACTIVATION_FUNC_TYPED(OUTPUT_REORDER, TO_OUTPUT_REORDER_TYPE(colorRGBA.s2), NL_M, NL_N);
|
||||
#if INPUT0_FEATURE_NUM == 4
|
||||
ov = RESHAPE_DIMS(INPUT0, OUTPUT, b, 3, v, u, w, z, y, x);
|
||||
output_idx = FUNC_CALL(get_output_index)(OPTIONAL_SHAPE_INFO_TENSOR ov.s0, ov.s1, ov.s2, ov.s3, ov.s4, ov.s5, ov.s6, ov.s7);
|
||||
output[output_idx] = ACTIVATION_FUNC_TYPED(OUTPUT_REORDER, TO_OUTPUT_REORDER_TYPE(colorRGBA.s3), NL_M, NL_N);
|
||||
#endif
|
||||
uint8 ov0 = RESHAPE_DIMS(INPUT0, OUTPUT, b, 0, v, u, w, z, y, x);
|
||||
uint8 ov1 = RESHAPE_DIMS(INPUT0, OUTPUT, b, 1, v, u, w, z, y, x);
|
||||
uint8 ov2 = RESHAPE_DIMS(INPUT0, OUTPUT, b, 2, v, u, w, z, y, x);
|
||||
uint output_idx_0 = FUNC_CALL(get_output_index)(OPTIONAL_SHAPE_INFO_TENSOR ov0.s0, ov0.s1, ov0.s2, ov0.s3, ov0.s4, ov0.s5, ov0.s6, ov0.s7);
|
||||
uint output_idx_1 = FUNC_CALL(get_output_index)(OPTIONAL_SHAPE_INFO_TENSOR ov1.s0, ov1.s1, ov1.s2, ov1.s3, ov1.s4, ov1.s5, ov1.s6, ov1.s7);
|
||||
uint output_idx_2 = FUNC_CALL(get_output_index)(OPTIONAL_SHAPE_INFO_TENSOR ov2.s0, ov2.s1, ov2.s2, ov2.s3, ov2.s4, ov2.s5, ov2.s6, ov2.s7);
|
||||
#if HAS_FUSED_OPS
|
||||
res = TO_OUTPUT_REORDER_TYPE(colorRGBA.s0);
|
||||
FUSED_OPS;
|
||||
output[output_idx_0] = FUSED_OPS_RESULT;
|
||||
res = TO_OUTPUT_REORDER_TYPE(colorRGBA.s1);
|
||||
FUSED_OPS;
|
||||
output[output_idx_1] = FUSED_OPS_RESULT;
|
||||
res = TO_OUTPUT_REORDER_TYPE(colorRGBA.s2);
|
||||
FUSED_OPS;
|
||||
output[output_idx_2] = FUSED_OPS_RESULT;
|
||||
#else
|
||||
output[output_idx_0] = ACTIVATION_FUNC_TYPED(OUTPUT_REORDER, TO_OUTPUT_REORDER_TYPE(colorRGBA.s0), NL_M, NL_N);
|
||||
output[output_idx_1] = ACTIVATION_FUNC_TYPED(OUTPUT_REORDER, TO_OUTPUT_REORDER_TYPE(colorRGBA.s1), NL_M, NL_N);
|
||||
output[output_idx_2] = ACTIVATION_FUNC_TYPED(OUTPUT_REORDER, TO_OUTPUT_REORDER_TYPE(colorRGBA.s2), NL_M, NL_N);
|
||||
#endif
|
||||
#if INPUT0_FEATURE_NUM == 4
|
||||
uint8 ov = RESHAPE_DIMS(INPUT0, OUTPUT, b, 3, v, u, w, z, y, x);
|
||||
uint output_idx = FUNC_CALL(get_output_index)(OPTIONAL_SHAPE_INFO_TENSOR ov.s0, ov.s1, ov.s2, ov.s3, ov.s4, ov.s5, ov.s6, ov.s7);
|
||||
#if HAS_FUSED_OPS
|
||||
res = TO_OUTPUT_REORDER_TYPE(colorRGBA.s3);
|
||||
FUSED_OPS;
|
||||
output[output_idx] = FUSED_OPS_RESULT;
|
||||
#else
|
||||
output[output_idx] = ACTIVATION_FUNC_TYPED(OUTPUT_REORDER, TO_OUTPUT_REORDER_TYPE(colorRGBA.s3), NL_M, NL_N);
|
||||
#endif
|
||||
#endif
|
||||
#elif OUTPUT_LAYOUT_IMAGE_2D_RGBA
|
||||
IMAGE_WRITE(output, (int2)(x, y), colorRGBA);
|
||||
#else
|
||||
#if INPUT0_IS_FP && !OUTPUT_IS_FP
|
||||
#if CONVERT_TRUNCATE
|
||||
output[output_idx] = ACTIVATION_TYPED(OUTPUT_REORDER, TO_OUTPUT_REORDER_TYPE(convert_long(res)), ACTIVATION_PARAMS_TYPED);
|
||||
#else
|
||||
output[output_idx] = ACTIVATION_TYPED(OUTPUT_REORDER, TO_OUTPUT_REORDER_TYPE_SAT(res), ACTIVATION_PARAMS_TYPED);
|
||||
#endif
|
||||
#else
|
||||
output[output_idx] = ACTIVATION_TYPED(OUTPUT_REORDER, TO_OUTPUT_REORDER_TYPE(res), ACTIVATION_PARAMS_TYPED);
|
||||
#endif
|
||||
#if INPUT0_IS_FP && !OUTPUT_IS_FP
|
||||
#if CONVERT_TRUNCATE
|
||||
#define __TO_OUTPUT_REORDER_TYPE(res) TO_OUTPUT_REORDER_TYPE(convert_long(res))
|
||||
#else
|
||||
#define __TO_OUTPUT_REORDER_TYPE(res) TO_OUTPUT_REORDER_TYPE_SAT(res)
|
||||
#endif
|
||||
#else
|
||||
#define __TO_OUTPUT_REORDER_TYPE(res) TO_OUTPUT_REORDER_TYPE(res)
|
||||
#endif
|
||||
|
||||
#if HAS_FUSED_OPS
|
||||
res = __TO_OUTPUT_REORDER_TYPE(res);
|
||||
FUSED_OPS;
|
||||
output[output_idx] = FUSED_OPS_RESULT;
|
||||
#else
|
||||
output[output_idx] = ACTIVATION_TYPED(OUTPUT_REORDER, __TO_OUTPUT_REORDER_TYPE(res), ACTIVATION_PARAMS_TYPED);
|
||||
#endif
|
||||
#undef __TO_OUTPUT_REORDER_TYPE
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,6 +41,17 @@ JitConstants ReorderKernelRef::GetJitConstants(const reorder_params& params) con
|
|||
if (params.surface_input)
|
||||
jit.AddConstant(MakeJitConstant("SURFACE_INPUT", true));
|
||||
|
||||
if (!params.fused_ops.empty()) {
|
||||
std::vector<std::string> idx_order;
|
||||
if (DataTensor::ChannelsCount(params.outputs[0].GetLayout()) == 4) {
|
||||
idx_order = {"b", "f", "y", "x"};
|
||||
} else if (DataTensor::ChannelsCount(params.outputs[0].GetLayout()) == 5) {
|
||||
idx_order = {"b", "f", "z", "y", "x"};
|
||||
}
|
||||
FusedOpsConfiguration conf = {"", idx_order, "res", GetUnitType(params), 1};
|
||||
jit.Merge(MakeFusedOpsJitConstants(params, {conf}));
|
||||
}
|
||||
|
||||
return jit;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -583,6 +583,55 @@ TEST(reorder_gpu_f32, basic_subtract_value) {
|
|||
}
|
||||
}
|
||||
|
||||
TEST(reorder_gpu_f32, fusing_double_activations) {
|
||||
// reorder_data reorder_data
|
||||
// | |
|
||||
// sqrt |
|
||||
// | fuse |
|
||||
// power data ----> | data
|
||||
// \ / | /
|
||||
// divide divide
|
||||
// | |
|
||||
// result result
|
||||
//
|
||||
// This test case is limited to the case of reorder_data using ReorderKernelRef.
|
||||
// Because other kernels for reorder_data don't support fusing double activations e.g. reorder_data_fast_b1
|
||||
//
|
||||
auto& engine = get_test_engine();
|
||||
|
||||
auto input1 = engine.allocate_memory({{1}, data_types::f32, format::bfyx});
|
||||
auto input2 = engine.allocate_memory({{1, 1, 1, 2, 2}, data_types::f32, format::bfzyx});
|
||||
|
||||
topology topology {
|
||||
input_layout("input1", input1->get_layout()),
|
||||
reorder("reorder", input_info("input1"), format::bfyx, data_types::f32),
|
||||
activation("sqrt", input_info("reorder"), activation_func::sqrt),
|
||||
activation("power", input_info("sqrt"), activation_func::pow),
|
||||
input_layout("input2", input2->get_layout()),
|
||||
eltwise("divide", {input_info("power"), input_info("input2")}, eltwise_mode::div),
|
||||
reorder("result", input_info("divide"), format::bfyx, data_types::f32)
|
||||
};
|
||||
|
||||
set_values(input1, {25000});
|
||||
set_values(input2, {0.1f, 0.2f, 0.5f, 1.0f});
|
||||
|
||||
ExecutionConfig config = get_test_default_config(engine);
|
||||
ov::intel_gpu::ImplementationDesc reorder_impl = {format::bfyx, "reorder_data"};
|
||||
config.set_property(ov::intel_gpu::force_implementations(ov::intel_gpu::ImplForcingMap{{"reorder", reorder_impl}}));
|
||||
|
||||
network network(engine, topology, config);
|
||||
network.set_input_data("input1", input1);
|
||||
network.set_input_data("input2", input2);
|
||||
|
||||
auto output = network.execute();
|
||||
|
||||
mem_lock<float> output_mem(output.at("result").get_memory(), network.get_stream());
|
||||
std::vector<int32_t> output_ref = {10, 5, 2, 1};
|
||||
for (size_t i = 0; i < output_mem.size(); ++i) {
|
||||
ASSERT_EQ(output_mem[i], output_ref[i]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(reorder_gpu_f16, basic_subtract_f32_output_f32) {
|
||||
// Input : 2x2x2x2 (FP16)
|
||||
// Output : 2x2x2x2 (FP32)
|
||||
|
|
|
|||
Loading…
Reference in New Issue