diff --git a/src/plugins/intel_gpu/src/kernel_selector/cl_kernels/reorder_data.cl b/src/plugins/intel_gpu/src/kernel_selector/cl_kernels/reorder_data.cl index da52d5af2da..2e76331812b 100644 --- a/src/plugins/intel_gpu/src/kernel_selector/cl_kernels/reorder_data.cl +++ b/src/plugins/intel_gpu/src/kernel_selector/cl_kernels/reorder_data.cl @@ -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 } diff --git a/src/plugins/intel_gpu/src/kernel_selector/kernels/reorder/reorder_kernel.cpp b/src/plugins/intel_gpu/src/kernel_selector/kernels/reorder/reorder_kernel.cpp index df5e7b48162..d4c8303d712 100644 --- a/src/plugins/intel_gpu/src/kernel_selector/kernels/reorder/reorder_kernel.cpp +++ b/src/plugins/intel_gpu/src/kernel_selector/kernels/reorder/reorder_kernel.cpp @@ -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 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; } diff --git a/src/plugins/intel_gpu/tests/unit/test_cases/reorder_gpu_test.cpp b/src/plugins/intel_gpu/tests/unit/test_cases/reorder_gpu_test.cpp index e4085c4ffe1..561ef4374d1 100644 --- a/src/plugins/intel_gpu/tests/unit/test_cases/reorder_gpu_test.cpp +++ b/src/plugins/intel_gpu/tests/unit/test_cases/reorder_gpu_test.cpp @@ -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 output_mem(output.at("result").get_memory(), network.get_stream()); + std::vector 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)