From 2f5bf75e512ba37b6729e17f7bfba474a5836d3c Mon Sep 17 00:00:00 2001 From: pengwa Date: Thu, 22 Dec 2022 15:12:52 +0800 Subject: [PATCH] Optimize computation orders (#13672) ### Optimize computation orders In `Roberta/Electra`, when `ClassificationHead` is used, there is slicing operation on features on sequence_length dimensions, then loss calculations only depend on this sliced data. This is a slicing at axis 1. Before slicing the shape is [batch, sequence_length, hidden], after slicing, it becomes [batch , hidden_stage] We had opportunities to bring this slicing earlier as much as possible, by passing through simple elementwise ops (like Add/Div), or Layernorm/Softmax(if their reduce axis is after the slicing axis), or even MatMul's the left operand (if only it did not affect the last dims). For operators like Reshape/Transpose, it is special since they have either data specified (after slicing we need update), or they have perm specified, which requires the input rank remain unchanged. So for those kinds of operators, we can remain the original rank, but just leave the sliced dim to be 1, after the compute completed, we do a Squeeze. ``` class RobertaClassificationHead(nn.Module): """Head for sentence-level classification tasks.""" def __init__(self, config): super().__init__() self.dense = nn.Linear(config.hidden_size, config.hidden_size) classifier_dropout = ( config.classifier_dropout if config.classifier_dropout is not None else config.hidden_dropout_prob ) self.dropout = nn.Dropout(classifier_dropout) self.out_proj = nn.Linear(config.hidden_size, config.num_labels) def forward(self, features, **kwargs): x = features[:, 0, :] # take token (equiv. to [CLS]) x = self.dropout(x) x = self.dense(x) x = torch.tanh(x) x = self.dropout(x) x = self.out_proj(x) return x ``` src\transformers\models\roberta\modeling_roberta.py src\transformers\models\electra\modeling_electra.py #### Benchmark A simple benchmark shows Robeta training latency dropped from 208ms ~ 199ms. 4.5+% reduction. More comprehensive tests are on the way. ### Motivation and Context --- cmake/onnxruntime_optimizer.cmake | 2 + docs/ORTModule_Training_Guidelines.md | 7 + .../core/optimizer/computation_reduction.cc | 305 ---- .../core/optimizer/computation_reduction.h | 18 - .../compute_optimizer/compute_optimizer.cc | 541 ++++++ .../compute_optimizer/compute_optimizer.h | 37 + .../compute_optimizer/passthrough_actors.cc | 844 +++++++++ .../compute_optimizer/passthrough_actors.h | 333 ++++ .../core/optimizer/graph_transformer_utils.cc | 4 +- .../test/optimizer/compute_optimizer_test.cc | 1596 +++++++++++++++++ .../test/optimizer/graph_transform_test.cc | 194 -- .../transform/computation_reduction/e2e.onnx | Bin 201861 -> 0 bytes .../gather/gather_matmul.py | 65 + .../gather/gather_matmul_batch_dim.onnx | Bin 0 -> 543 bytes .../gather/gather_matmul_last_dim.onnx | Bin 0 -> 533 bytes .../gather_matmul_scalar_batch_dim.onnx | Bin 0 -> 533 bytes .../gather/gather_matmul_scalar_last_dim.onnx | Bin 0 -> 523 bytes .../gather_matmul_scalar_second_last_dim.onnx | Bin 0 -> 523 bytes .../gather/gather_matmul_second_last_dim.onnx | Bin 0 -> 533 bytes .../gather/gather_reshape.py | 89 + .../gather/gather_reshape_batch_dim.onnx | Bin 0 -> 494 bytes .../gather_reshape_scalar_batch_dim.onnx | Bin 0 -> 484 bytes .../gather_reshape_scalar_seqlen_dim.onnx | Bin 0 -> 474 bytes .../gather_reshape_scalar_seqlen_dim2.onnx | Bin 0 -> 446 bytes .../gather/gather_reshape_seqlen_dim.onnx | Bin 0 -> 484 bytes .../gather/gather_reshape_seqlen_dim2.onnx | Bin 0 -> 487 bytes .../gather/gather_roberta_e2e.onnx | Bin 0 -> 7064 bytes .../gather/gather_roberta_e2e.py | 211 +++ .../computation_reduction/gathernd/e2e.onnx | Bin 0 -> 202225 bytes .../{ => gathernd}/e2e.py | 25 +- .../gathernd/gathernd_add.onnx | Bin 0 -> 1660 bytes .../{ => gathernd}/gathernd_add.py | 5 +- .../gathernd/gathernd_div.onnx | Bin 0 -> 1672 bytes .../{ => gathernd}/gathernd_div.py | 5 +- .../{ => gathernd}/gathernd_gelu.onnx | Bin 377 -> 427 bytes .../{ => gathernd}/gathernd_gelu.py | 5 +- .../gathernd/gathernd_layernormalization.onnx | Bin 0 -> 1743 bytes .../gathernd_layernormalization.py | 5 +- .../gathernd/gathernd_matmul.onnx | Bin 0 -> 66013 bytes .../{ => gathernd}/gathernd_matmul.py | 5 +- .../computation_reduction/gathernd_add.onnx | Bin 1610 -> 0 bytes .../computation_reduction/gathernd_div.onnx | Bin 1622 -> 0 bytes .../gathernd_layernormalization.onnx | Bin 1693 -> 0 bytes .../gathernd_matmul.onnx | Bin 65963 -> 0 bytes .../core/optimizer/graph_transformer_config.h | 3 + .../core/optimizer/graph_transformer_utils.cc | 19 +- .../models/runner/training_runner.cc | 3 +- .../python/orttraining_pybind_state.cc | 1 + .../ortmodule/_graph_execution_manager.py | 7 + .../test/training_api/core/checkpoint_test.cc | 18 +- .../cuda/communication/nccl_service.h | 2 +- 51 files changed, 3802 insertions(+), 547 deletions(-) delete mode 100644 onnxruntime/core/optimizer/computation_reduction.cc delete mode 100644 onnxruntime/core/optimizer/computation_reduction.h create mode 100644 onnxruntime/core/optimizer/compute_optimizer/compute_optimizer.cc create mode 100644 onnxruntime/core/optimizer/compute_optimizer/compute_optimizer.h create mode 100644 onnxruntime/core/optimizer/compute_optimizer/passthrough_actors.cc create mode 100644 onnxruntime/core/optimizer/compute_optimizer/passthrough_actors.h create mode 100644 onnxruntime/test/optimizer/compute_optimizer_test.cc delete mode 100755 onnxruntime/test/testdata/transform/computation_reduction/e2e.onnx create mode 100755 onnxruntime/test/testdata/transform/computation_reduction/gather/gather_matmul.py create mode 100644 onnxruntime/test/testdata/transform/computation_reduction/gather/gather_matmul_batch_dim.onnx create mode 100644 onnxruntime/test/testdata/transform/computation_reduction/gather/gather_matmul_last_dim.onnx create mode 100644 onnxruntime/test/testdata/transform/computation_reduction/gather/gather_matmul_scalar_batch_dim.onnx create mode 100644 onnxruntime/test/testdata/transform/computation_reduction/gather/gather_matmul_scalar_last_dim.onnx create mode 100644 onnxruntime/test/testdata/transform/computation_reduction/gather/gather_matmul_scalar_second_last_dim.onnx create mode 100644 onnxruntime/test/testdata/transform/computation_reduction/gather/gather_matmul_second_last_dim.onnx create mode 100755 onnxruntime/test/testdata/transform/computation_reduction/gather/gather_reshape.py create mode 100644 onnxruntime/test/testdata/transform/computation_reduction/gather/gather_reshape_batch_dim.onnx create mode 100644 onnxruntime/test/testdata/transform/computation_reduction/gather/gather_reshape_scalar_batch_dim.onnx create mode 100644 onnxruntime/test/testdata/transform/computation_reduction/gather/gather_reshape_scalar_seqlen_dim.onnx create mode 100644 onnxruntime/test/testdata/transform/computation_reduction/gather/gather_reshape_scalar_seqlen_dim2.onnx create mode 100644 onnxruntime/test/testdata/transform/computation_reduction/gather/gather_reshape_seqlen_dim.onnx create mode 100644 onnxruntime/test/testdata/transform/computation_reduction/gather/gather_reshape_seqlen_dim2.onnx create mode 100644 onnxruntime/test/testdata/transform/computation_reduction/gather/gather_roberta_e2e.onnx create mode 100755 onnxruntime/test/testdata/transform/computation_reduction/gather/gather_roberta_e2e.py create mode 100755 onnxruntime/test/testdata/transform/computation_reduction/gathernd/e2e.onnx rename onnxruntime/test/testdata/transform/computation_reduction/{ => gathernd}/e2e.py (88%) create mode 100644 onnxruntime/test/testdata/transform/computation_reduction/gathernd/gathernd_add.onnx rename onnxruntime/test/testdata/transform/computation_reduction/{ => gathernd}/gathernd_add.py (94%) create mode 100644 onnxruntime/test/testdata/transform/computation_reduction/gathernd/gathernd_div.onnx rename onnxruntime/test/testdata/transform/computation_reduction/{ => gathernd}/gathernd_div.py (94%) rename onnxruntime/test/testdata/transform/computation_reduction/{ => gathernd}/gathernd_gelu.onnx (69%) rename onnxruntime/test/testdata/transform/computation_reduction/{ => gathernd}/gathernd_gelu.py (91%) create mode 100644 onnxruntime/test/testdata/transform/computation_reduction/gathernd/gathernd_layernormalization.onnx rename onnxruntime/test/testdata/transform/computation_reduction/{ => gathernd}/gathernd_layernormalization.py (94%) create mode 100644 onnxruntime/test/testdata/transform/computation_reduction/gathernd/gathernd_matmul.onnx rename onnxruntime/test/testdata/transform/computation_reduction/{ => gathernd}/gathernd_matmul.py (92%) delete mode 100644 onnxruntime/test/testdata/transform/computation_reduction/gathernd_add.onnx delete mode 100644 onnxruntime/test/testdata/transform/computation_reduction/gathernd_div.onnx delete mode 100644 onnxruntime/test/testdata/transform/computation_reduction/gathernd_layernormalization.onnx delete mode 100644 onnxruntime/test/testdata/transform/computation_reduction/gathernd_matmul.onnx diff --git a/cmake/onnxruntime_optimizer.cmake b/cmake/onnxruntime_optimizer.cmake index 306c6a9b55..0cb8103630 100644 --- a/cmake/onnxruntime_optimizer.cmake +++ b/cmake/onnxruntime_optimizer.cmake @@ -57,6 +57,8 @@ else() "${ONNXRUNTIME_INCLUDE_DIR}/core/optimizer/*.h" "${ONNXRUNTIME_ROOT}/core/optimizer/*.h" "${ONNXRUNTIME_ROOT}/core/optimizer/*.cc" + "${ONNXRUNTIME_ROOT}/core/optimizer/compute_optimizer/*.h" + "${ONNXRUNTIME_ROOT}/core/optimizer/compute_optimizer/*.cc" "${ONNXRUNTIME_ROOT}/core/optimizer/qdq_transformer/*.h" "${ONNXRUNTIME_ROOT}/core/optimizer/qdq_transformer/*.cc" "${ONNXRUNTIME_ROOT}/core/optimizer/qdq_transformer/selectors_actions/*.h" diff --git a/docs/ORTModule_Training_Guidelines.md b/docs/ORTModule_Training_Guidelines.md index 49375f5891..42dd4bad10 100644 --- a/docs/ORTModule_Training_Guidelines.md +++ b/docs/ORTModule_Training_Guidelines.md @@ -124,6 +124,13 @@ Before full qualified name can be got from exporter, this environment variables export ORTMODULE_SKIPPED_AUTOGRAD_FUNCTIONS="megatron.fp16.fp16.fused_kernels.GELUFunction" ``` +#### ORTMODULE_ENABLE_COMPUTE_OPTIMIZER + +- **Feature Area**: *ORTMODULE/Optimizations* +- **Description**: By default, this is enabled then some computation can be saved. This env var can be used for disabling +the optimization to guarantee exactly same compute with baseline (for example PyTorch, when doing convergence parity +debugging). + ### 2.2 Memory Optimization Q: *Want to run a bigger batch size?* diff --git a/onnxruntime/core/optimizer/computation_reduction.cc b/onnxruntime/core/optimizer/computation_reduction.cc deleted file mode 100644 index f1ccc9f877..0000000000 --- a/onnxruntime/core/optimizer/computation_reduction.cc +++ /dev/null @@ -1,305 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#include "core/common/safeint.h" -#include "core/graph/graph_utils.h" -#include "core/optimizer/initializer.h" -#include "core/optimizer/utils.h" -#include "core/optimizer/computation_reduction.h" - -using namespace ONNX_NAMESPACE; -using namespace ::onnxruntime::common; -namespace onnxruntime { -typedef std::function Handler; - -constexpr int GATHERND_BATCH_DIM = 1; - -static bool IsLeadingDimsEqual(const TensorShapeProto* input_shape, const TensorShapeProto* output_shape, - const int num_dim_to_check) { - ORT_ENFORCE(output_shape->dim_size() >= num_dim_to_check && input_shape->dim_size() >= num_dim_to_check); - - for (int i = 0; i < num_dim_to_check; ++i) { - auto& output_dim = output_shape->dim(i); - auto& input_dim = input_shape->dim(i); - if (output_dim.has_dim_value() && input_dim.has_dim_value()) { - if (output_dim.dim_value() != input_dim.dim_value()) { - return false; - } - } else if (output_dim.has_dim_param() && input_dim.has_dim_param()) { - if (output_dim.dim_param() != input_dim.dim_param()) { - return false; - } - } else { - return false; - } - } - - return true; -} - -static int GetValidInputForGatherND(const Node& target_node) { - // target_node is the producer of GatherND's input. - // If target_node's some input tensors have exactly same shape with - // target_node output tensor shape, then it is safe to gather using - // original slice ranges. - int candidate_input_index = -1; - auto output_shape = target_node.OutputDefs()[0]->Shape(); - const int output_rank = output_shape->dim_size(); - for (size_t i = 0; i < target_node.InputDefs().size(); ++i) { - auto input_shape = target_node.InputDefs()[i]->Shape(); - const int input_rank = input_shape->dim_size(); - if (input_rank != output_rank) { - continue; - } - - if (IsLeadingDimsEqual(input_shape, output_shape, GATHERND_BATCH_DIM + 1)) { - candidate_input_index = SafeInt(i); - break; - } - } - - return candidate_input_index; -} - -static TensorShapeProto ReplaceSymbolicDimValue(const TensorShapeProto* shape, const int replacement_axis, - const std::string& replacement_dim_value) { - ORT_ENFORCE(replacement_axis >= 0 && replacement_axis < shape->dim_size()); - TensorShapeProto output_shape; - for (int i = 0; i < shape->dim_size(); ++i) { - auto& dim = shape->dim(i); - if (i == replacement_axis) { - output_shape.add_dim()->set_dim_param(replacement_dim_value); - continue; - } - - if (dim.has_dim_value()) { - output_shape.add_dim()->set_dim_value(dim.dim_value()); - } else if (dim.has_dim_param()) { - output_shape.add_dim()->set_dim_param(dim.dim_param()); - } else { - ORT_THROW("Invalid dim found in ReplaceSymbolicDimValue"); - } - } - - return output_shape; -} - -static Status SwapGatherNDWithTargetNode(Graph& graph, Node& gathernd_node, Node& target_node, - const int target_node_input_index = 0) { - auto new_input_arg_for_gathernd = target_node.MutableInputDefs()[target_node_input_index]; - auto target_node_out_arg = target_node.MutableOutputDefs()[0]; - auto gathernd_out_arg = gathernd_node.MutableOutputDefs()[0]; - auto gathernd_old_consumers = graph.GetConsumerNodes(gathernd_out_arg->Name()); - const auto& graph_outputs = graph.GetOutputs(); - bool need_update_graph_output = false; - if (std::find(graph_outputs.begin(), graph_outputs.end(), gathernd_out_arg) != graph_outputs.end()) { - need_update_graph_output = true; - } - - const std::string& gathered_dim_param = gathernd_out_arg->Shape()->dim(GATHERND_BATCH_DIM).dim_param(); - TensorShapeProto new_output_shape_for_gathernd = - ReplaceSymbolicDimValue(new_input_arg_for_gathernd->Shape(), GATHERND_BATCH_DIM, gathered_dim_param); - - TensorShapeProto new_output_shape_for_target_node = - ReplaceSymbolicDimValue(target_node_out_arg->Shape(), GATHERND_BATCH_DIM, gathered_dim_param); - - // update input/output definitions. - int output_index = optimizer_utils::IndexOfNodeOutput(target_node, *gathernd_node.MutableInputDefs()[0]); - graph.RemoveEdge(target_node.Index(), gathernd_node.Index(), output_index, 0); - const Node* target_node_input_node = graph.GetProducerNode(new_input_arg_for_gathernd->Name()); - if (target_node_input_node != nullptr) { - output_index = optimizer_utils::IndexOfNodeOutput(*target_node_input_node, *new_input_arg_for_gathernd); - graph.AddEdge(target_node_input_node->Index(), gathernd_node.Index(), output_index, 0); - } else { - // new_input_arg_for_gathernd is graph input - graph_utils::ReplaceNodeInput(gathernd_node, 0, *new_input_arg_for_gathernd); - } - - graph_utils::ReplaceDownstreamNodeInput(graph, gathernd_node, 0 /*output_idx*/, - target_node, 0 /*replacement_output_idx*/); - - if (target_node_input_node != nullptr) { - graph.RemoveEdge(target_node_input_node->Index(), target_node.Index(), output_index, target_node_input_index); - } - graph.AddEdge(gathernd_node.Index(), target_node.Index(), 0, target_node_input_index); - - // update consumer relation ship - if (!gathernd_old_consumers.empty()) { - graph.UpdateConsumerNodes(target_node_out_arg->Name(), {const_cast(gathernd_old_consumers[0])}); - } - graph.UpdateConsumerNodes(gathernd_out_arg->Name(), {&target_node}); - - // update shapes - gathernd_out_arg->SetShape(new_output_shape_for_gathernd); - target_node_out_arg->SetShape(new_output_shape_for_target_node); - - if (need_update_graph_output) { - InlinedVector graph_new_outputs; - graph_new_outputs.reserve(graph_outputs.size()); - for (auto out_arg : graph_outputs) { - if (out_arg->Name().compare(gathernd_out_arg->Name()) == 0) { - graph_new_outputs.push_back(target_node_out_arg); - } else { - graph_new_outputs.push_back(out_arg); - } - } - graph.SetOutputs(graph_new_outputs); - graph.SetGraphResolveNeeded(); - graph.SetGraphProtoSyncNeeded(); - } - - return Status::OK(); -} - -static Status SimpleHandler(Graph& graph, Node& gathernd_node, Node& target_node) { - return SwapGatherNDWithTargetNode(graph, gathernd_node, target_node, 0); -} - -/* - This handler change the graphs this way: - Before: - input_1[b,s,h] weight_2[h] - \ / - Add[b,s,h] indices[b,p_s,1] - | / - GatherND[b,p_s,h] - | - - After : - input_1[b,s,h] indices[b,p_s,1] - | / - GatherND[b,p_s,h] weight_2[h] - \ / - Add[b,p_s,h] - | - - Note: b: batch, s: sequence_length, h: hidden_size, p_s: dynamic_prediction_count -*/ -static Status BinaryElementwiseHandler(Graph& graph, Node& gathernd_node, Node& target_node) { - int target_node_input_index = GetValidInputForGatherND(target_node); - ORT_RETURN_IF(target_node_input_index == -1, "Invalid target node index"); - return SwapGatherNDWithTargetNode(graph, gathernd_node, target_node, target_node_input_index); -} - -/* - This handler change the graphs this way: - Before: - input_1[b,s,h] weight_2[h, 2h] - \ / - MatMul[b,s,2h] indices[b,p_s,1] - | / - GatherND[b,p_s,2h] - | - - After : - input_1[b,s,h] indices[b,p_s,1] - | / - GatherND[b,p_s,h] weight_2[h,2h] - \ / - MatMul[b,p_s,2h] - | - - Note: b: batch, s: sequence_length, h: hidden_size, p_s: dynamic_prediction_count -*/ -static Status MatMulHandler(Graph& graph, Node& gathernd_node, Node& target_node) { - int target_node_input_index = GetValidInputForGatherND(target_node); - ORT_RETURN_IF_NOT(target_node_input_index == 0, "target_node_input_index != 0"); - return SwapGatherNDWithTargetNode(graph, gathernd_node, target_node, target_node_input_index); -} - -static std::unordered_map handlers = { - {"Add", BinaryElementwiseHandler}, - {"Div", BinaryElementwiseHandler}, - {"Gelu", SimpleHandler}, - {"LayerNormalization", SimpleHandler}, - {"MatMul", MatMulHandler}}; - -static Status Delegate(Graph& graph, Node& gathernd_node, Node& target_node) { - const std::string& op_type = target_node.OpType(); - if (handlers.count(op_type)) { - return handlers[op_type](graph, gathernd_node, target_node); - } else { - return common::Status(common::ONNXRUNTIME, common::NOT_IMPLEMENTED, op_type + " handler is not implemented"); - } -} - -Status ComputationReductionTransformer::ApplyImpl(Graph& graph, bool& modified, int graph_level, - const logging::Logger& logger) const { - GraphViewer graph_viewer(graph); - const auto& order = graph_viewer.GetNodesInTopologicalOrder(); - - for (auto index : order) { - auto* node_ptr = graph.GetNode(index); - if (!node_ptr) - // node was removed, this should not happen since we are not removing nodes. - continue; - - auto& node = *node_ptr; - ORT_RETURN_IF_ERROR(Recurse(node, modified, graph_level, logger)); - - // Same ideas might apply for Gather, GatherElements, Slice, Split, etc. - // TODO: let's review the real cases to make the logic more generic. - if (!graph_utils::IsSupportedOptypeVersionAndDomain(node, "GatherND", {1, 12, 13}, kOnnxDomain) || - !graph_utils::IsSupportedProvider(node, GetCompatibleExecutionProviders()) || - node.GetOutputEdgesCount() > 1) { // allow GatherND have no out edges in case it is graph output. - continue; - } - - auto batch_dims = static_cast(node.GetAttributes().at("batch_dims").i()); - if (batch_dims != GATHERND_BATCH_DIM) { - continue; - } - - auto indices_shape = node.MutableInputDefs()[1]->Shape(); - if (indices_shape == nullptr) { - continue; - } - - const auto indices_rank = indices_shape->dim_size(); - auto& indices_last_dim = indices_shape->dim(indices_rank - 1); - // Since GatherND is assumed to have batch_dims=1, if the input data's shape is [batch, sequence, ..., ... ], - // limiting indices_rank=3 will make sure produced output is in shape [batch, sliced_sequence, ..., ...] - // and the rank did not change. - if (!(indices_last_dim.has_dim_value() && indices_last_dim.dim_value() == 1 && indices_rank == 3)) { - continue; - } - - // Todo: check whether we want to move GatherND up, for example, if GatherND's outputs are larger - // than inputs, we should NOT probably bring it ahead. - bool stop = false; - while (!stop) { - const Node* gathernd_data_producer = graph.GetProducerNode(node.MutableInputDefs()[0]->Name()); - if (gathernd_data_producer == nullptr) { - break; - } - Node* input_node = const_cast(gathernd_data_producer); - if (graph.GetConsumerNodes(input_node->MutableOutputDefs()[0]->Name()).size() > 1) { - LOGS_DEFAULT(WARNING) << "node " << node.Name() << " stopped at node " - << input_node->Name(); - break; - } - - auto ret = Delegate(graph, node, *input_node); - if (ret.IsOK()) { - LOGS_DEFAULT(WARNING) << "node " << node.Name() << " up across node " - << input_node->Name() << std::endl; - modified = true; - } else if (ret.Code() == common::NOT_IMPLEMENTED) { - LOGS_DEFAULT(WARNING) << "node " << node.Name() << " stopped at node " - << input_node->Name(); - break; - } else { - LOGS_DEFAULT(WARNING) << " terminate due to unexpected error, node names:" << node.Name() - << ", " << input_node->Name() << ", error " << ret.ErrorMessage() << std::endl; - stop = true; - } - } - } - - if (modified) { - graph.SetGraphResolveNeeded(); - } - return Status::OK(); -} - -} // namespace onnxruntime diff --git a/onnxruntime/core/optimizer/computation_reduction.h b/onnxruntime/core/optimizer/computation_reduction.h deleted file mode 100644 index 1f44b7ee4a..0000000000 --- a/onnxruntime/core/optimizer/computation_reduction.h +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#pragma once - -#include "core/optimizer/graph_transformer.h" - -namespace onnxruntime { - -class ComputationReductionTransformer : public GraphTransformer { - public: - ComputationReductionTransformer(const InlinedHashSet& compatible_execution_providers = {}) noexcept - : GraphTransformer("ComputationReductionTransformer", compatible_execution_providers) {} - - Status ApplyImpl(Graph& graph, bool& modified, int graph_level, const logging::Logger& logger) const override; -}; - -} // namespace onnxruntime diff --git a/onnxruntime/core/optimizer/compute_optimizer/compute_optimizer.cc b/onnxruntime/core/optimizer/compute_optimizer/compute_optimizer.cc new file mode 100644 index 0000000000..2bf3aa2cc7 --- /dev/null +++ b/onnxruntime/core/optimizer/compute_optimizer/compute_optimizer.cc @@ -0,0 +1,541 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#ifdef ENABLE_TRAINING +#include + +#include "core/common/safeint.h" +#include "core/graph/graph_utils.h" +#include "core/optimizer/initializer.h" +#include "core/optimizer/utils.h" +#include "core/optimizer/compute_optimizer/passthrough_actors.h" +#include "core/optimizer/compute_optimizer/compute_optimizer.h" + +using SliceInfo = onnxruntime::optimizer::compute_optimizer::SliceInfo; +using namespace onnxruntime::optimizer::compute_optimizer; +namespace onnxruntime { + +namespace { + +bool EnforceNodeAllInputOutputHaveShapes(const Node& node) { + for (const auto* input_def : node.InputDefs()) { + if (!input_def->Shape()) { + return false; + } + } + + for (const auto* output_def : node.OutputDefs()) { + if (!output_def->Shape()) { + return false; + } + } + return true; +} + +using OPSET_VERSION_LIST = std::initializer_list; +const OPSET_VERSION_LIST opset_1{1}; +const OPSET_VERSION_LIST opset_13_1{13, 1}; +const OPSET_VERSION_LIST opset_13_9_1{13, 9, 1}; +const OPSET_VERSION_LIST opset_13_11_1{13, 11, 1}; +const OPSET_VERSION_LIST opset_13_9_6_1{13, 9, 6, 1}; +const OPSET_VERSION_LIST opset_14_13_5_1{14, 13, 5, 1}; +const OPSET_VERSION_LIST opset_14_13_7_6_1{14, 13, 7, 6, 1}; +const OPSET_VERSION_LIST opset_13_12_10_7_6_1{13, 12, 10, 7, 6, 1}; + +/** + * @brief Functor to trigger the optimization search for a given slicing node + * (for example Gather/GatherND node). + */ +struct SliceOperationReorderHandle { + /** + * @brief Pass through configuration for specific operator. + * + * For each operator: + * > `input_indices` can be used to explicitly specify the input indices that Slicing op can be passed through. + * This could be helpful if some inputs are not applicable for pass through. If not specified, all inputs + * are considered (but there will be checks to ignore those inputs that are not affected by the slicing axis). + * > `actor` will be used to perform the actual pass through, including both pre-check stage and post process + * stage. + */ + struct OpPassThroughConfig { + OpPassThroughConfig(const std::vector& input_indices, + std::shared_ptr actor, + const OPSET_VERSION_LIST& opset_list) + : input_indices(input_indices), actor(actor), opsets(opset_list) { + } + + std::vector input_indices; + std::shared_ptr actor; + const OPSET_VERSION_LIST& opsets; + }; + + static std::string GetFullQualifiedOpName(const std::string& op_type, const std::string& domain) { + return domain + "::" + op_type; + } + + static std::unordered_map& GetOpPassThroughConfigMap() { + static std::unordered_map allowed_passthrough_ops; + static std::once_flag allowed_ops_init; + std::call_once(allowed_ops_init, []() { + allowed_passthrough_ops.insert({ + // Things to consider when more operators are added here: + // 1. Whether the operator is safe to pass through in term of compute equivalence. + // If optype is not enough to guarantee the equivalence, we need to add a customized pre-check function + // (as LayerNormalization did). + // 2. Whether the outputs have the same dim changes if Gather node moves before that operator. + // 3. Should all inputs be allowed when track back further (bottom-up); + // if not, add the input index restriction as MatMul did. + {GetFullQualifiedOpName("Add", kOnnxDomain), + OpPassThroughConfig({}, std::make_shared(), opset_14_13_7_6_1)}, + {GetFullQualifiedOpName("BiasGelu", kMSDomain), + OpPassThroughConfig({}, std::make_shared(), opset_1)}, + {GetFullQualifiedOpName("BitmaskBiasDropout", kMSDomain), + OpPassThroughConfig({}, std::make_shared(), opset_1)}, + {GetFullQualifiedOpName("Cast", kOnnxDomain), + OpPassThroughConfig({}, std::make_shared(), opset_13_9_6_1)}, + {GetFullQualifiedOpName("Div", kOnnxDomain), + OpPassThroughConfig({}, std::make_shared(), opset_14_13_7_6_1)}, + {GetFullQualifiedOpName("Dropout", kOnnxDomain), + OpPassThroughConfig({}, std::make_shared(), opset_13_12_10_7_6_1)}, + {GetFullQualifiedOpName("Gelu", kMSDomain), + OpPassThroughConfig({}, std::make_shared(), opset_1)}, + {// Be noted, this is our own implementation of ONNX domain op. + GetFullQualifiedOpName("LayerNormalization", kOnnxDomain), + OpPassThroughConfig({0}, std::make_shared(), opset_1)}, + {GetFullQualifiedOpName("MatMul", kOnnxDomain), + OpPassThroughConfig({}, std::make_shared(), opset_13_9_1)}, + {GetFullQualifiedOpName("Reshape", kOnnxDomain), + OpPassThroughConfig({0}, std::make_shared(), opset_14_13_5_1)}, + {GetFullQualifiedOpName("Softmax", kOnnxDomain), + OpPassThroughConfig({0}, std::make_shared(), opset_13_11_1)}, + {GetFullQualifiedOpName("Transpose", kOnnxDomain), + OpPassThroughConfig({}, std::make_shared(), opset_13_1)}, + }); + }); + + return allowed_passthrough_ops; + } + + SliceOperationReorderHandle(const std::string& node_name) : entry_node_name_(node_name) { + } + + bool operator()(Graph& graph, Node& current_node, SliceInfo& info, const logging::Logger& logger, + std::deque& queue); + + private: + /** + * @brief Pass through Slicing op from current_node's output to its specific input. + * + * Propagate the slicing operation into current_node's current_input_index-th input, e.g. a slicing op is inserted + * between current_node's current_input_index-th input and current_node. For example, if current_node is Add, + * and slice_node is a Gather(axis=1, indices=[1]): + * + * input_0 [M, N, K] input_1 [M, N, K] + * \ / + * Add [M, N, K] + * | + * Gather0(axis=1, indices=[1]) + * | + * output [M, 1, K] + * + * After the pass through, the graph will be: + * + * input_0 [M, N, K] input_1 [M, N, K] + * \ / + * Gather1(axis=1, indices=[1]) Gather2(axis=1, indices=[1]) + * \ / + * \ / + * \ / + * Add [M, N, K] + * | + * Gather0(axis=1, indices=[1]) + * | + * output [M, 1, K] + * + * Be noted: Gather1 and Gather2 are inserted on Add's two inputs. + * Gather0's removal and Add's output shape update is done in RemoveOriginSlicingOp. + * + * + * @param graph Graph to iterate. + * @param slice_node Slicing op node the takes current_node's output as input. + * @param current_node Current node. + * @param current_node_input_index The current_node_input_index-th input to propagate the Slice op pass through. + * @param info slice_node's SliceInfo. + * @param logger Logger. + * @param new_axis The new axis (for the new Slice op) upon current_node's original current_node_input_index-th input. + * @return SliceInfo for new created slicing op. + */ + SliceInfo PropagateSlicingForInput(Graph& graph, Node& slice_node, Node& current_node, int current_node_input_index, + SliceInfo& info, int new_axis, const logging::Logger& logger); + + /** + * @brief Remove the origin slicing op (for example Gather/GatherND) and update shapes. + * + * In the above example, the graph will be cleaned up to: + * input_0 [M, N, K] input_1 [M, N, K] + * \ / + * Gather1(axis=1, indices=[1]) Gather2(axis=1, indices=[1]) + * \ / + * \ / + * \ / + * Add [M, 1, K] + * | + * | + * output [M, 1, K] + * + * Be noted: Gather0 is removed, Add's output shape is updated. + * + * @param graph Graph to iterate. + * @param slice_node Slicing op node the takes current_node's output as input. + * @param current_node Current node. + * @param logger Logger. + * @param info slice_node's SliceInfo. + * @return + */ + Status RemoveOriginSlicingOp(Graph& graph, Node& slice_node, Node& current_node, + const logging::Logger& logger, SliceInfo& info); + + std::string entry_node_name_; +}; + +bool SliceOperationReorderHandle::operator()(Graph& graph, Node& current_node, + SliceInfo& info, + const logging::Logger& logger, + std::deque& queue) { + Node& slice_node = *info.node_ptr; + const std::string& op_type = GetFullQualifiedOpName(current_node.OpType(), current_node.Domain()); + if (GetOpPassThroughConfigMap().count(op_type)) { + auto& pass_through_config = GetOpPassThroughConfigMap().at(op_type); + LOG_DEBUG_INFO(logger, "Enter reorder handle for node " + current_node.Name() + "(" + op_type + ")"); + + if (!graph_utils::IsSupportedOptypeVersionAndDomain(current_node, current_node.OpType(), + pass_through_config.opsets, current_node.Domain())) { + LOG_DEBUG_INFO(logger, "Unsupported opset for " + current_node.Name() + "(" + op_type + ") since version: " + + std::to_string(current_node.SinceVersion())); + return false; + } + + if (!EnforceNodeAllInputOutputHaveShapes(current_node)) { + LOG_DEBUG_INFO(logger, "Some inputs/outputs' shape not found for node " + current_node.Name() + "(" + + op_type + ")"); + return false; + } + + std::unordered_map candidate_input_indices; + bool input_has_dim_1_for_axis = false; + if (!pass_through_config.actor->PreCheck(graph, current_node, info, pass_through_config.input_indices, logger, + candidate_input_indices, input_has_dim_1_for_axis)) { + LOG_DEBUG_INFO(logger, "Pre-check failed for " + current_node.Name() + "(" + op_type + ")"); + return false; + } + + if (candidate_input_indices.empty()) { + LOG_DEBUG_INFO(logger, "Skip handling current node " + current_node.Name() + "(" + op_type + + ") because the requirement is not met."); + return false; + } + + // Be noted, once we reach this point after PreCheck, graph modification started, any failure after this should + // be reported as ERROR. + std::vector populated_slicing_infos; // Slicing infos that are populated into current_node's inputs. + populated_slicing_infos.reserve(candidate_input_indices.size()); + std::unordered_map new_gather_infos; + for (auto pair : candidate_input_indices) { + auto input_index = pair.first; // input index of current_node + int new_axis = pair.second; // new axis of current_node's input to be sliced + SliceInfo gather_info = PropagateSlicingForInput(graph, slice_node, current_node, input_index, info, new_axis, + logger); + + ORT_ENFORCE(gather_info.node_ptr, "New added gather node should not be null."); + populated_slicing_infos.push_back(gather_info); + new_gather_infos.insert({{input_index, gather_info}}); + } + + int index_of_output = + optimizer_utils::IndexOfNodeOutput(current_node, *slice_node.InputDefs()[info.GetDataInputIndex()]); + ORT_ENFORCE(RemoveOriginSlicingOp(graph, slice_node, current_node, logger, info).IsOK()); + if (!pass_through_config.actor->PostProcess(graph, current_node, index_of_output, info.non_negative_axis, + info.is_scalar_slice, input_has_dim_1_for_axis, + info.output_dim_on_axis, + entry_node_name_, new_gather_infos, + logger)) { + ORT_THROW("Post-process failed for " + current_node.Name() + "(" + op_type + ")"); + } + + queue.insert(queue.end(), populated_slicing_infos.begin(), populated_slicing_infos.end()); + return true; + } else { + LOG_DEBUG_INFO(logger, "op_type not supported for " + current_node.Name() + "(" + op_type + ")"); + return false; + } +} + +SliceInfo SliceOperationReorderHandle::PropagateSlicingForInput(Graph& graph, + Node& slice_node, + Node& current_node, + int current_node_input_index, + SliceInfo& info, + int new_axis, + const logging::Logger& logger) { + LOG_DEBUG_INFO(logger, "PropagateSlicingForInput for Node " + slice_node.Name() + "(" + slice_node.OpType() + + ") with input index " + std::to_string(current_node_input_index) + ", keep_dim = " + + std::to_string(!info.is_scalar_slice)); + + InlinedVector input_args; + input_args.reserve(slice_node.InputDefs().size()); + // The first slice op's data input should be current_node's current_node_input_index-th input. + // For some cases when rank changes, slice op's slice input should also be adapted. + input_args.push_back(current_node.MutableInputDefs()[current_node_input_index]); + for (size_t i = 1; i < slice_node.InputDefs().size(); ++i) { + input_args.push_back(slice_node.MutableInputDefs()[i]); + } + + // Update the axis attribute if new_axis is not same with the original slicing axis (which happens when data + // layout got changed by Transpose or Reshape ops) + onnxruntime::NodeAttributes attributes = slice_node.GetAttributes(); + if (info.non_negative_axis != new_axis) { + attributes[info.axis_attr_name] = + ONNX_NAMESPACE::MakeAttribute(info.axis_attr_name, static_cast(new_axis)); + } + + InlinedVector output_args; + output_args.push_back( + &graph.GetOrCreateNodeArg(graph.GenerateNodeArgName(info.entry_slice_arg_name), + current_node.MutableInputDefs()[current_node_input_index]->TypeAsProto())); + + /* new node input index to connect to current_node's input node*/ + int new_slice_input_index_to_connect = info.GetDataInputIndex(); + /* new node output index to connect to current_node*/ + int new_slice_output_index_to_connect = info.GetOutputIndex(); + Node* new_slice_node = InsertIntermediateNodeOnDestInput(graph, current_node, + current_node_input_index, + new_slice_input_index_to_connect, + new_slice_output_index_to_connect, + graph.GenerateNodeName(info.entry_slice_arg_name), + slice_node.OpType(), + "Duplicated Gather node", + input_args, + output_args, + attributes, + slice_node.Domain(), + logger); + + new_slice_node->SetExecutionProviderType(slice_node.GetExecutionProviderType()); + + // Set correct shape for new created node. + auto new_slice_out_arg = new_slice_node->MutableOutputDefs()[new_slice_output_index_to_connect]; + int reversed_axis = new_axis - new_slice_out_arg->Shape()->dim_size(); + UpdateSliceOutputShape(*new_slice_out_arg, reversed_axis, info.output_dim_on_axis); + auto new_slice_info = SliceInfo(new_slice_node, info.is_scalar_slice, info.axis_attr_name, new_axis); + new_slice_info.entry_slice_arg_name = info.entry_slice_arg_name; + return new_slice_info; +} + +Status SliceOperationReorderHandle::RemoveOriginSlicingOp(Graph& graph, Node& slice_node, Node& current_node, + const logging::Logger& logger, SliceInfo& info) { + LOG_DEBUG_INFO(logger, "RemoveOriginSlicingOp target_node " + current_node.Name() + "(" + current_node.OpType() + + ") slice_node " + slice_node.Name() + "(" + slice_node.OpType() + "), keep_dim = " + + std::to_string(!(info.is_scalar_slice))); + + auto slice_input_arg = slice_node.MutableInputDefs()[info.GetDataInputIndex()]; + int slice_input_rank = slice_input_arg->Shape()->dim_size(); + int output_index = optimizer_utils::IndexOfNodeOutput(current_node, *slice_input_arg); + auto slice_op_output_arg = slice_node.MutableOutputDefs()[info.GetOutputIndex()]; + + // Loop all outputs of target node, update the shape accordingly. + // For elementwise ops like (LayerNorm/Dropout/Add), we should handle all outputs. + // If some output rank is lower than sliced axis, we should just ignore it (the correctness is guaranteed by devs + // who adds more operator coverage in the pass through). + for (size_t i = 0; i < current_node.MutableOutputDefs().size(); ++i) { + UpdateSliceOutputShape(*current_node.MutableOutputDefs()[i], info.non_negative_axis - slice_input_rank, + info.output_dim_on_axis); + } + LOG_DEBUG_INFO(logger, "RemoveOriginSlicingOp Replace all usage of output " + slice_op_output_arg->Name() + ":0" + + " with " + current_node.MutableOutputDefs()[output_index]->Name() + ":" + + std::to_string(output_index)); + + graph_utils::ReplaceDownstreamNodeInput(graph, slice_node, info.GetOutputIndex() /*output_idx*/, current_node, + output_index /*replacement_output_idx*/); + auto gather_origin_consumer_nodes = graph.GetConsumerNodes(slice_op_output_arg->Name()); + std::vector slice_op_consumers; + slice_op_consumers.reserve(gather_origin_consumer_nodes.size()); + for (auto& consumer_node : gather_origin_consumer_nodes) { + slice_op_consumers.push_back(graph.GetNode(consumer_node->Index())); + LOG_DEBUG_INFO(logger, "RemoveOriginSlicingOp Gather's consumer node " + consumer_node->Name() + "(" + + consumer_node->OpType() + ")"); + } + graph.UpdateConsumerNodes(current_node.OutputDefs()[output_index]->Name(), slice_op_consumers); + + graph.UpdateConsumerNodes(slice_op_output_arg->Name(), {}); + graph.RemoveNode(slice_node.Index()); + + return Status::OK(); +} + +} // namespace + +std::optional ComputeOptimizer::IsSupportedGatherND(Graph& /*graph*/, Node& node, + const logging::Logger& logger) const { + if (!graph_utils::IsSupportedOptypeVersionAndDomain(node, "GatherND", {1, 12, 13}, kOnnxDomain) || + !graph_utils::IsSupportedProvider(node, GetCompatibleExecutionProviders())) { + return std::nullopt; + } + + auto data_shape = node.MutableInputDefs()[0]->Shape(); + auto indices_shape = node.MutableInputDefs()[1]->Shape(); + auto gather_out_shape = node.MutableOutputDefs()[0]->Shape(); + if (data_shape == nullptr || indices_shape == nullptr || gather_out_shape == nullptr) { + LOG_DEBUG_INFO(logger, "Skip GatherND node " + node.Name() + " due to undefined shape."); + return std::nullopt; + } + + const auto data_rank = data_shape->dim_size(); + const auto indices_rank = indices_shape->dim_size(); + + // batch_dims is an integer indicating the number of batch dimensions, + // i.e the leading b number of dimensions of data tensor and indices are representing the batches, + // and the gather starts from the b+1 dimension. + auto batch_dims = static_cast(node.GetAttributes().at("batch_dims").i()); + ORT_ENFORCE(batch_dims >= 0 && batch_dims < indices_rank && batch_dims < data_rank, + "batch_dims must be in the range [0, min(indices_rank, data_rank)):" + std::to_string(batch_dims) + + " indices_rank:" + std::to_string(indices_rank) + " data_rank:" + std::to_string(data_rank)); + + // Since GatherND is assumed to have batch_dims=1, if the input data's shape is [batch, sequence, ..., ... ], + // limiting indices_rank=3 will make sure produced output is in shape [batch, sliced_sequence, ..., ...] + // and the rank did not change. + // TODO: release the constraint here. + if (data_rank != 3 || indices_rank != 3 || batch_dims != 1) { + return std::nullopt; + } + + auto& indices_last_dim = indices_shape->dim(indices_rank - 1); + if (!(indices_last_dim.has_dim_value() && indices_last_dim.dim_value() == 1)) { + return std::nullopt; + } + + return SliceInfo(&node, false, "batch_dims", static_cast(batch_dims), true); +} + +std::optional ComputeOptimizer::IsSupportedGather(Graph& /*graph*/, Node& node, + const logging::Logger& logger) const { + if (!graph_utils::IsSupportedOptypeVersionAndDomain(node, "Gather", {1, 11, 13}, kOnnxDomain) || + !graph_utils::IsSupportedProvider(node, GetCompatibleExecutionProviders())) { + return std::nullopt; + } + + auto data_shape = node.MutableInputDefs()[0]->Shape(); + auto indices_shape = node.MutableInputDefs()[1]->Shape(); + auto gather_out_shape = node.MutableOutputDefs()[0]->Shape(); + if (data_shape == nullptr || indices_shape == nullptr || gather_out_shape == nullptr) { + LOG_DEBUG_INFO(logger, "Skip Gather node " + node.Name() + " due to undefined shape."); + return std::nullopt; + } + + const auto data_rank = data_shape->dim_size(); + if (data_rank <= 1) { + LOG_DEBUG_INFO(logger, "Skip Gather node " + node.Name() + " due to rank <= 1."); + return std::nullopt; + } + + auto axis = static_cast(node.GetAttributes().at("axis").i()); + axis = axis < 0 ? axis + data_rank : axis; + size_t dim_size = static_cast(indices_shape->dim_size()); + bool is_single_value_1d_tensor = dim_size != 0 && (dim_size == 1 && utils::HasDimValue(indices_shape->dim(0)) && + indices_shape->dim(0).dim_value() == 1); + if (dim_size != 0 && !is_single_value_1d_tensor) { + if (dim_size == 1 && utils::HasDimValue(data_shape->dim(axis)) && + data_shape->dim(axis).dim_value() > indices_shape->dim(0).dim_value()) { + // Can support. + } else { + LOG_DEBUG_INFO(logger, "Skip Gather node " + node.Name() + " due to unsupported dim size: " + + std::to_string(dim_size)); + return std::nullopt; + } + } + + return SliceInfo(&node, dim_size == 0, "axis", axis, true); +} + +Status ComputeOptimizer::ApplyImpl(Graph& graph, bool& modified, int graph_level, const logging::Logger& logger) + const { + LOG_DEBUG_INFO(logger, "Enter ComputeOptimizer"); + bool reordered = false; + GraphViewer graph_viewer(graph); + const auto& order = graph_viewer.GetNodesInTopologicalOrder(); + const auto& graph_outputs = graph.GetOutputs(); + size_t reordered_node_count = 0; // For summary + for (auto index : order) { + auto* node_ptr = graph.GetNode(index); + if (!node_ptr) + // node was removed. + continue; + + auto& node = *node_ptr; + ORT_RETURN_IF_ERROR(Recurse(node, modified, graph_level, logger)); + + std::optional gather_info; + // Same ideas might apply for GatherElements, Slice, Split, etc.. + gather_info = IsSupportedGatherND(graph, node, logger); + if (!gather_info.has_value()) { + gather_info = IsSupportedGather(graph, node, logger); + } + + if (!gather_info.has_value()) { + continue; + } + + auto& output_arg = node.MutableOutputDefs()[0]; + if (std::find(graph_outputs.begin(), graph_outputs.end(), output_arg) != graph_outputs.end()) { + continue; + } + + std::string node_name = node.Name(); + std::string node_type = node.OpType(); + std::deque gather_queue; + gather_queue.push_back(gather_info.value()); + + std::string log_prefix = "Entry node " + node_name + " (" + node_type + ") with axis " + + std::to_string(gather_info.value().non_negative_axis); + LOG_DEBUG_INFO(logger, log_prefix + " starts re-ordering check"); + + SliceOperationReorderHandle handle(node_name); + + // DON'T operate on `node` once this loop starts, as it may be removed from the graph. + while (!gather_queue.empty()) { + SliceInfo info = gather_queue.front(); + Node* gather_node = info.node_ptr; + gather_queue.pop_front(); + Node* slice_input_data_producer = + graph.GetMutableProducerNode(gather_node->MutableInputDefs()[0]->Name()); + if (slice_input_data_producer == nullptr) { + break; + } + Node* input_node = slice_input_data_producer; + if (graph.GetConsumerNodes(input_node->MutableOutputDefs()[0]->Name()).size() > 1) { + LOG_DEBUG_INFO(logger, log_prefix + " stops at node " + input_node->Name() + " since multiple consumer found"); + continue; + } + + auto ret = handle(graph, *input_node, info, logger, gather_queue); + if (ret) { + LOG_DEBUG_INFO(logger, log_prefix + " moves up across node " + input_node->Name()); + modified = true; + reordered = true; + } else { + LOG_DEBUG_INFO(logger, log_prefix + " stops when handling " + input_node->Name()); + } + } + + if (reordered) { + ++reordered_node_count; + } + } + + LOGS(logger, INFO) << "Exit ComputeOptimizer with summary - reorderd_node_count:" << reordered_node_count + << " nodes."; + return Status::OK(); +} + +} // namespace onnxruntime + +#endif diff --git a/onnxruntime/core/optimizer/compute_optimizer/compute_optimizer.h b/onnxruntime/core/optimizer/compute_optimizer/compute_optimizer.h new file mode 100644 index 0000000000..934d3ea4bb --- /dev/null +++ b/onnxruntime/core/optimizer/compute_optimizer/compute_optimizer.h @@ -0,0 +1,37 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#ifdef ENABLE_TRAINING +#pragma once + +#include "core/optimizer/compute_optimizer/passthrough_actors.h" +#include "core/optimizer/graph_transformer.h" +#include "core/optimizer/utils.h" + +namespace onnxruntime { + +/** + * @brief Graph transformer that helps reduce compute FLOP while maintaining mathematically equivalent result. + * + * This graph transformation tries to identify opportunities to reduce unnecessary computations on the graph level. + * Currently, the major optimization is to bring some slice operators ahead as much as possible, to leave more ops + * operate on sliced input data. Gather and GatherND are the entry operators that trigger the optimization search. + * + * In terms of file dependency, compute_optimizer.h/cc reference structs and utilities defined in + * passthrough_actors.h/cc. + */ +class ComputeOptimizer : public GraphTransformer { + public: + using SliceInfo = onnxruntime::optimizer::compute_optimizer::SliceInfo; + ComputeOptimizer(const InlinedHashSet& compatible_execution_providers = {}) noexcept + : GraphTransformer("ComputeOptimizer", compatible_execution_providers) {} + + Status ApplyImpl(Graph& graph, bool& modified, int graph_level, const logging::Logger& logger) const override; + + private: + std::optional IsSupportedGatherND(Graph& graph, Node& node, const logging::Logger& logger) const; + std::optional IsSupportedGather(Graph& graph, Node& node, const logging::Logger& logger) const; +}; + +} // namespace onnxruntime +#endif diff --git a/onnxruntime/core/optimizer/compute_optimizer/passthrough_actors.cc b/onnxruntime/core/optimizer/compute_optimizer/passthrough_actors.cc new file mode 100644 index 0000000000..82c5084b03 --- /dev/null +++ b/onnxruntime/core/optimizer/compute_optimizer/passthrough_actors.cc @@ -0,0 +1,844 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#ifdef ENABLE_TRAINING +#include + +#include "core/common/safeint.h" +#include "core/graph/graph_utils.h" +#include "core/optimizer/initializer.h" +#include "core/optimizer/utils.h" +#include "core/optimizer/compute_optimizer/passthrough_actors.h" +#include "core/optimizer/compute_optimizer/compute_optimizer.h" + +using namespace ONNX_NAMESPACE; +using namespace ::onnxruntime::common; +namespace onnxruntime::optimizer::compute_optimizer { + +enum class DimCompareRet { + ExactEqual = 0, + BroadcastableEqual = 1, + RankTooLow = 2, + NotEqual = 3, + DimCompareRetMax = 4, +}; + +/** + * @brief Check dimensions are equal or broadcastable before axis. + * + * @param full_broadcasted_shape Full broadcasted shape as a baseline to compare. + * @param axis The axis (inclusive, of full_broadcasted_shape) where we end the comparison. + * @param target_shape Shape to compare, can have dim value be 1 for broadcastable dimension. + * @return A pair of bool, bool. The first bool is true if the dimensions are exactly same before and include axis. + * The second bool is true if the dimension of target_shape has dim value be 1 on axis. + */ +std::pair AreDimsCompatibleBeforeAxisInternal( + const TensorShapeProto* full_broadcasted_shape, const int axis, + const TensorShapeProto* target_shape) { + int full_rank = full_broadcasted_shape->dim_size(); + int target_rank = target_shape->dim_size(); + + ORT_ENFORCE(full_rank >= axis && target_rank <= full_rank, "full_rank should bigger than axis and target_rank ", + axis, " full_rank: ", full_rank, " target_rank: ", target_rank); + + int minimum_rank_to_handle = full_rank - axis; + if (target_rank < minimum_rank_to_handle) { + // Skip if target node's input rank is less than minimum rank to handle. + // Essentially this means the input did not affect the Gather axis. + return std::make_pair(DimCompareRet::RankTooLow, false); + } + + bool exact_equal = true; + bool broadcastable_equal = true; + bool dim_be_1_on_axis = false; + + int axis_iter = axis; + int negative_axis = axis < 0 ? axis : axis - full_rank; + int target_axis_iter = target_rank + negative_axis; + + for (; axis_iter >= 0 && target_axis_iter >= 0; --axis_iter, --target_axis_iter) { + auto& dim = full_broadcasted_shape->dim(axis_iter); + auto& target_dim = target_shape->dim(target_axis_iter); + if (dim.has_dim_value() && target_dim.has_dim_value()) { + if (dim.dim_value() != target_dim.dim_value()) { + exact_equal = false; + if (target_dim.dim_value() == 1) { + if (axis_iter == axis) dim_be_1_on_axis = true; + } else { + broadcastable_equal = false; + } + } + } else if (dim.has_dim_param() && target_dim.has_dim_param()) { + if (dim.dim_param() != target_dim.dim_param()) { + exact_equal = false; + } + } else { + exact_equal = false; + if (target_dim.has_dim_value() && target_dim.dim_value() == 1) { + if (axis_iter == axis) dim_be_1_on_axis = true; + } else { + broadcastable_equal = false; + } + } + } + + if (exact_equal) { + return std::make_pair(DimCompareRet::ExactEqual, dim_be_1_on_axis); + } else if (broadcastable_equal) { + return std::make_pair(DimCompareRet::BroadcastableEqual, dim_be_1_on_axis); + } else { + return std::make_pair(DimCompareRet::NotEqual, dim_be_1_on_axis); + } +} + +/** + * @brief Check input meet pass through requirement. + * + * @param current_node_output_arg_to_gather The output arg of current node that consumed by slice node. + * @param arg_to_compare The input/output arg to check. + * @param info Slice info. + * @param logger The logger. + * @param fatal_error_found Used as return value. If fatal error found, set to true. Fatal error means, + * we cannot pass through this input arg. + * @param dim_1_for_axis_found Used as return value. If dim value is 1 for axis, set to true. + * @return a int represent the new slice axis for the input arg, if pass through needed to be done for + * this input arg, otherwise, return nullptr. + * + * For each input of current_node, using this function to check if the input can be passed through. + * If the input has dim on negative_axis and + * 1). either the dimension (if exists) including and before negative_axis is same as target node's output shape. + * 2). or the dimension (if exists) including and before negative_axis is 1. + * Otherwise, we will skip the optimization. + * + * Example 1: [Can be passed through] + * input_0 [M, N, K] input_1 [K] + * \ / + * Add [M, N, K] (current_node) + * | + * Gather0(axis=1, indices=[1]) + * | + * output [M, 1, K] + * In this case, we can propagate Gather to input_0 branch, input_1 is skipped because it did not has dim on + * slicing axis. + * + * Example 2: [Can be passed through] + * input_0 [M, N, K] input_1 [N, K] + * \ / + * Add [M, N, K] (current_node) + * | + * Gather0(axis=1, indices=[1]) + * | + * output [M, 1, K] + * In this case, we can propagate Gather to input_0 and input-1 branch, because including and before slicing axis 1, + * all dims are equal. + * + * Example 3: [Can be passed through] + * input_0 [M, N, K] input_1 [1, K] + * \ / + * Add [M, N, K] (current_node) + * | + * Gather0(axis=1, indices=[1]) + * | + * output [M, 1, K] + * In this case, we can propagate Gather to input_0 branch, input_1 branch is skipped because it has dim 1 on slicing + * axis. + * + * Example 4: [Can be passed through] + * input_0 [M, N, K] input_1 [1, N, K] + * \ / + * Add [M, N, K] (current_node) + * | + * Gather0(axis=1, indices=[1]) + * | + * output [M, 1, K] + * In this case, we can propagate Gather to input_0 and input_1 branch. + * + * Example 5: [Can be passed through] + * input_0 [M, N, K] input_1 [M, 1, K] + * \ / + * Add [M, N, K] (current_node) + * | + * Gather0(axis=1, indices=[1]) + * | + * output [M, 1, K] + * In this case, we can propagate Gather to input_0 branch, input_1 branch is skipped because it has dim 1 on slicing. + * + * Example 6: [CANNOT be passed through] + * input_0 [M, N, K] input_1 [L, N, K] + * \ / + * Add [M, N, K] (current_node) + * | + * Gather0(axis=1, indices=[1]) + * | + * output [M, 1, K] + * + */ +std::optional CheckInputForPassThrough(const NodeArg* current_node_output_arg_to_gather, + const NodeArg* arg_to_compare, + const SliceInfo& info, + const logging::Logger& logger, + bool& fatal_error_found, + bool& dim_1_for_axis_found) { + fatal_error_found = false; + auto ret_pair = AreDimsCompatibleBeforeAxisInternal(current_node_output_arg_to_gather->Shape(), + info.non_negative_axis, + arg_to_compare->Shape()); + if (ret_pair.first == DimCompareRet::ExactEqual) { + return info.non_negative_axis; + } else if (ret_pair.first == DimCompareRet::RankTooLow) { + LOG_DEBUG_INFO(logger, "Skip " + arg_to_compare->Name() + " because its rank is too low."); + return std::nullopt; + } else if (ret_pair.first == DimCompareRet::NotEqual) { + fatal_error_found = true; + return std::nullopt; + } else if (ret_pair.first == DimCompareRet::BroadcastableEqual) { + if (ret_pair.second) { + LOG_DEBUG_INFO(logger, "Skip " + arg_to_compare->Name() + + ", whose dim on axis is 1, no need to Gather from."); + dim_1_for_axis_found = true; + return std::nullopt; + } + return info.non_negative_axis; + } + + ORT_THROW("Unexpected return value from CheckInputForPassThrough."); +} + +/** + * @brief From given TensorShape, update specified dimension with given value. + * If no new_dim is provided, the dimension will be removed. + * + * @param shape TensorShape used as base shape to modify. + * @param axis The dimension to be replaced/removed. + * @param new_dim The new dimension value. If not provided, the dimension will be removed. + * @return TensorShapeProto A copy of "shape" after modification. + */ +TensorShapeProto CreateNewShapeWithUpdatedDim(const TensorShapeProto* shape, const int axis, + const TensorShapeProto_Dimension& new_dim) { + ORT_ENFORCE(axis >= 0 && axis < shape->dim_size()); + TensorShapeProto output_shape; + for (int i = 0; i < shape->dim_size(); ++i) { + auto& dim = shape->dim(i); + if (i == axis) { + if (new_dim.has_dim_value()) { + output_shape.add_dim()->set_dim_value(new_dim.dim_value()); + } else if (new_dim.has_dim_param()) { + output_shape.add_dim()->set_dim_param(new_dim.dim_param()); + } else { + // do nothing, unassigned dim will be removed. + } + + continue; + } + + if (dim.has_dim_value()) { + output_shape.add_dim()->set_dim_value(dim.dim_value()); + } else if (dim.has_dim_param()) { + output_shape.add_dim()->set_dim_param(dim.dim_param()); + } else { + ORT_THROW("Invalid dim found in CreateNewShapeWithUpdatedDim"); + } + } + + return output_shape; +} + +bool UpdateSliceOutputShape(NodeArg& arg_to_update, int reverse_axis, const TensorShapeProto_Dimension& output_dim_on_axis) { + ORT_ENFORCE(reverse_axis < 0, " reverse_axis should be negative, representing the index from right to left."); + const TensorShapeProto* shape = arg_to_update.Shape(); + int rank = shape->dim_size(); + if (rank < -reverse_axis) { + return false; + } + + int axis_to_update = rank + reverse_axis; + TensorShapeProto new_output_shape = CreateNewShapeWithUpdatedDim(shape, axis_to_update, output_dim_on_axis); + arg_to_update.SetShape(new_output_shape); + return true; +} + +Node* InsertIntermediateNodeOnDestInput(Graph& graph, + Node& dest_node, int dest_in_index, + int new_node_input_index, + int new_node_output_index, + const std::string& name, const std::string& op_type, + const std::string& description, + const InlinedVector& input_args, + const InlinedVector& output_args, + const onnxruntime::NodeAttributes& attributes, + const std::string& domain, + const logging::Logger& logger) { + LOG_DEBUG_INFO(logger, "Inserting " + op_type + " node on " + dest_node.Name() + " 's " + + std::to_string(dest_in_index) + "th input " + + dest_node.InputDefs()[dest_in_index]->Name() + ", and connect inserted node's " + + std::to_string(new_node_output_index) + "th output to " + dest_node.Name() + " 's " + + std::to_string(dest_in_index) + "th input."); + + ORT_ENFORCE(dest_in_index < static_cast(dest_node.InputDefs().size())); + ORT_ENFORCE(new_node_input_index < static_cast(input_args.size()), "new_node_input_index is out of range."); + ORT_ENFORCE(new_node_output_index < static_cast(output_args.size()), "new_node_output_index is out of range."); + ORT_ENFORCE(dest_node.MutableInputDefs()[dest_in_index] == input_args[new_node_input_index], + "input_args[new_node_input_index] is not the same as dest_node.MutableInputDefs()[dest_in_index].", + dest_node.MutableInputDefs()[dest_in_index]->Name(), " vs ", input_args[new_node_input_index]->Name()); + + // Prepare Input and Outputs for the duplicated Gather/GatherND node. + NodeArg* src_node_arg = dest_node.MutableInputDefs()[dest_in_index]; + + // Create the duplicated Gather/GatherND node. + Node& new_node = graph.AddNode(name, op_type, description, input_args, output_args, &attributes, domain); + ORT_ENFORCE(graph.SetOpSchemaFromRegistryForNode(new_node), "Failed to set op schema for " + new_node.Name()); + + // Connect dest_node's input node to duplicated node. + // Update new node producer and consumer map. + for (size_t j = 0; j < new_node.MutableOutputDefs().size(); ++j) { + graph.UpdateProducerNode(new_node.MutableOutputDefs()[j]->Name(), new_node.Index()); + } + graph.AddConsumerNode(src_node_arg->Name(), &new_node); + const Node* src_node = graph.GetProducerNode(src_node_arg->Name()); + if (src_node) { + int src_out_index = optimizer_utils::IndexOfNodeOutput(*src_node, *src_node_arg); + graph.AddEdge(src_node->Index(), new_node.Index(), src_out_index, new_node_input_index); + } + + // Remove edge between dest_node and src_node. + // Be noted, this will remove dest_node's input edges to src_node + // (and also the src_node's output edges to dest_node). + std::vector input_edge_to_remove; + input_edge_to_remove.reserve(1); + for (auto it = dest_node.InputEdgesBegin(), end = dest_node.InputEdgesEnd(); it != end; ++it) { + LOG_DEBUG_INFO(logger, "dest_node " + dest_node.Name() + " input edge: " + it->GetNode().Name() + + " output index: " + std::to_string(it->GetSrcArgIndex()) + " input index: " + + std::to_string(it->GetDstArgIndex())); + if (it->GetDstArgIndex() == dest_in_index) { + input_edge_to_remove.push_back(graph_utils::GraphEdge::CreateGraphEdge(dest_node, *it, true)); + break; + } + } + + // If the input is graph input or initializer, no edge will be removed. + if (input_edge_to_remove.size() > 0) { + graph_utils::GraphEdge::RemoveGraphEdges(graph, input_edge_to_remove); + + // Remove target node from target input arg's consumer list. + const std::string& src_node_arg_name = src_node_arg->Name(); + int input_use_count_by_dest_node = 0; + for (size_t i = 0; i < dest_node.InputDefs().size(); ++i) { + if (dest_node.InputDefs()[i]->Name().compare(src_node_arg_name) == 0) { + ++input_use_count_by_dest_node; + } + } + + if (input_use_count_by_dest_node == 1) { + graph.RemoveConsumerNode(src_node_arg_name, &dest_node); + } + } + + // Connect duplicated gather node to target node's input. + dest_node.MutableInputDefs()[dest_in_index] = new_node.MutableOutputDefs()[new_node_output_index]; + // Add new edge connecting the duplicated gather with the target node directly. + // This also updates the destination node's input node args + graph.AddEdge(new_node.Index(), dest_node.Index(), new_node_output_index, dest_in_index); + graph.AddConsumerNode(new_node.MutableOutputDefs()[new_node_output_index]->Name(), &dest_node); + LOG_DEBUG_INFO(logger, "Inserted " + op_type + " node on " + dest_node.Name() + " 's " + + std::to_string(dest_in_index) + "th input " + + dest_node.InputDefs()[dest_in_index]->Name()); + return &new_node; +} + +TensorShapeProto CreateTensorShapeInsertDimAtAxis(const TensorShapeProto* src_shape, int axis, int64_t dim_value) { + ORT_ENFORCE(axis <= src_shape->dim_size(), "axis is out of range.", axis, " vs ", src_shape->dim_size()); + TensorShapeProto updated_shape; + int j = 0; + for (j = 0; j < axis; ++j) { + auto dim = src_shape->dim(j); + if (dim.has_dim_value()) { + updated_shape.add_dim()->set_dim_value(dim.dim_value()); + } else if (dim.has_dim_param()) { + updated_shape.add_dim()->set_dim_param(dim.dim_param()); + } else { + ORT_THROW("Invalid dim found in CreateTensorShapeInsertDimAtAxis"); + } + } + updated_shape.add_dim()->set_dim_value(dim_value); + for (; j < src_shape->dim_size(); ++j) { + auto dim = src_shape->dim(j); + if (dim.has_dim_value()) { + updated_shape.add_dim()->set_dim_value(dim.dim_value()); + } else if (dim.has_dim_param()) { + updated_shape.add_dim()->set_dim_param(dim.dim_param()); + } else { + ORT_THROW("Invalid dim found in CreateTensorShapeInsertDimAtAxis"); + } + } + return updated_shape; +} + +NodeArg* CreateUnsqueezeAxesInitializer(Graph& graph, const std::vector& values) { + ONNX_NAMESPACE::TensorProto axes_const_tensor; + axes_const_tensor.set_name(graph.GenerateNodeArgName("axes")); + axes_const_tensor.set_data_type(ONNX_NAMESPACE::TensorProto_DataType_INT64); + axes_const_tensor.add_dims(values.size()); + axes_const_tensor.set_raw_data(values.data(), values.size() * sizeof(int64_t)); + return &graph_utils::AddInitializer(graph, axes_const_tensor); +} + +int GetONNXOpSetVersion(const Graph& graph) { + int onnx_opset = -1; + auto onnx_domain_it = graph.DomainToVersionMap().find(kOnnxDomain); + if (onnx_domain_it != graph.DomainToVersionMap().end()) { + onnx_opset = onnx_domain_it->second; + } else { + auto onnx_domain_alias_it = graph.DomainToVersionMap().find(kOnnxDomainAlias); + if (onnx_domain_alias_it != graph.DomainToVersionMap().end()) + onnx_opset = onnx_domain_alias_it->second; + else + ORT_THROW("ONNX domain not found in this model"); + } + return onnx_opset; +} + +void AdaptInputAndOutputForScalarSlice(Graph& graph, Node& current_node, int current_node_output_index, + int slice_axis, const std::string& entry_node_name, + const std::unordered_map& new_gather_infos, + const logging::Logger& logger) { + LOG_DEBUG_INFO(logger, "AdaptInputAndOutputForScalarSlice for Node " + current_node.Name() + "(" + + current_node.OpType() + ")"); + + // For each handled inputs, insert Unsqueeze node to get the removed dim back at slice_axis. + for (auto pair : new_gather_infos) { + int input_index = pair.first; + Node* new_node = nullptr; + // Be noted, the Unsqueeze should happens on the axis of new slice node. + if (GetONNXOpSetVersion(graph) < 13) { + onnxruntime::NodeAttributes attributes; + attributes["axes"] = ONNX_NAMESPACE::MakeAttribute("axes", std::vector{pair.second.non_negative_axis}); + + new_node = + InsertIntermediateNodeOnDestInput( + graph, + current_node, input_index, + 0 /* new node input index to connect to current_node's input node*/, + 0 /* new node output index to connect to current_node*/, + graph.GenerateNodeName(entry_node_name + "_adapt_input"), + "Unsqueeze", + "Unsqueeze node", + {current_node.MutableInputDefs()[input_index]}, + {&graph.GetOrCreateNodeArg( + graph.GenerateNodeArgName("unsqueeze_adaptor"), + current_node.MutableInputDefs()[input_index]->TypeAsProto())}, + attributes, kOnnxDomain, + logger); + } else { + new_node = + InsertIntermediateNodeOnDestInput( + graph, + current_node, input_index, + 0 /* new node input index to connect to current_node's input node*/, + 0 /* new node output index to connect to current_node*/, + graph.GenerateNodeName(entry_node_name + "_adapt_input"), + "Unsqueeze", + "Unsqueeze node", + {current_node.MutableInputDefs()[input_index], + CreateUnsqueezeAxesInitializer(graph, {pair.second.non_negative_axis})}, + {&graph.GetOrCreateNodeArg( + graph.GenerateNodeArgName("unsqueeze_adaptor"), + current_node.MutableInputDefs()[input_index]->TypeAsProto())}, + {}, kOnnxDomain, + logger); + } + new_node->SetExecutionProviderType(current_node.GetExecutionProviderType()); + // Set correct shape for Unsqueeze node + const TensorShapeProto* unsqueeze_input_shape = new_node->MutableInputDefs()[0]->Shape(); + new_node->MutableOutputDefs()[0]->SetShape( + CreateTensorShapeInsertDimAtAxis(unsqueeze_input_shape, pair.second.non_negative_axis, 1)); + } + + // Find the consumer node of MatMul, and the input index of that node connect to MatMul. + std::vector consumers = + graph.GetConsumerNodes(current_node.MutableOutputDefs()[current_node_output_index]->Name()); + ORT_ENFORCE(consumers.size() >= 1, "MatMul should have at least one consumer at this point. " + + std::to_string(consumers.size()) + " consumers found."); + Node& consumer = *graph.GetNode(consumers[0]->Index()); + int index = -1; + for (size_t i = 0; i < consumer.InputDefs().size(); ++i) { + auto input_arg = consumer.InputDefs()[i]; + if (input_arg->Name().compare(current_node.MutableOutputDefs()[current_node_output_index]->Name()) == 0) { + index = static_cast(i); + break; + } + } + + // Create Squeeze node connecting MatMul output to consumer node. + Node* matmul_out_adaptor_node = nullptr; + if (GetONNXOpSetVersion(graph) < 13) { + onnxruntime::NodeAttributes attributes; + attributes["axes"] = ONNX_NAMESPACE::MakeAttribute("axes", std::vector{slice_axis}); + matmul_out_adaptor_node = + InsertIntermediateNodeOnDestInput( + graph, consumer, index, + 0, + 0 /* new node output index*/, + graph.GenerateNodeName(current_node.OpType() + "_output"), + "Squeeze", + "Squeeze node", + {consumer.MutableInputDefs()[index]}, + {&graph.GetOrCreateNodeArg( + graph.GenerateNodeArgName("squeeze_adaptor"), + consumer.MutableInputDefs()[index]->TypeAsProto())}, + attributes, kOnnxDomain, logger); + } else { + matmul_out_adaptor_node = + InsertIntermediateNodeOnDestInput( + graph, consumer, index, + 0, + 0 /* new node output index*/, + graph.GenerateNodeName(current_node.OpType() + "_output"), + "Squeeze", + "Squeeze node", + {consumer.MutableInputDefs()[index], + CreateUnsqueezeAxesInitializer(graph, {slice_axis})}, + {&graph.GetOrCreateNodeArg( + graph.GenerateNodeArgName("squeeze_adaptor"), + consumer.MutableInputDefs()[index]->TypeAsProto())}, + {}, kOnnxDomain, logger); + } + + matmul_out_adaptor_node->SetExecutionProviderType(current_node.GetExecutionProviderType()); + + // Don't need set shape for Squeeze because original MatMul output is used as its output type. + // Set correct shape for MatMul node + const TensorShapeProto* matmul_out_shape = matmul_out_adaptor_node->MutableOutputDefs()[0]->Shape(); + current_node.MutableOutputDefs()[0]->SetShape(CreateTensorShapeInsertDimAtAxis(matmul_out_shape, slice_axis, 1)); +} + +bool DefaultOperatorPassThroughActorBase::PostProcess( + Graph& graph, Node& current_node, int current_node_output_index, + int slice_axis, bool is_slice_scalar, bool input_has_dim_1_for_axis, + const ONNX_NAMESPACE::TensorShapeProto_Dimension& /*output_dim_on_axis*/, + const std::string& entry_node_name, + const std::unordered_map& new_gather_infos, + const logging::Logger& logger) { + LOG_DEBUG_INFO(logger, "Enter DefaultOperatorPassThroughActorBase::PostProcess for Node " + current_node.Name() + + "(" + current_node.OpType() + ")"); + if (is_slice_scalar && input_has_dim_1_for_axis) { + AdaptInputAndOutputForScalarSlice(graph, current_node, current_node_output_index, slice_axis, + entry_node_name, new_gather_infos, logger); + } + + return true; +} + +bool SimplePassThroughActor::PreCheck(const Graph& /*graph*/, const Node& current_node, const SliceInfo& info, + const std::vector& allowed_input_indices, + const logging::Logger& logger, + std::unordered_map& propagate_input_config, + bool& input_has_dim_1_for_axis) { + LOG_DEBUG_INFO(logger, "Enter SimplePassThroughActor::PreCheck for node " + current_node.Name()); + + Node* slice_node = info.node_ptr; + int current_node_output_index = optimizer_utils::IndexOfNodeOutput(current_node, *slice_node->InputDefs()[0]); + const NodeArg* gather_data_input_arg = current_node.OutputDefs()[current_node_output_index]; + + propagate_input_config.clear(); + input_has_dim_1_for_axis = false; + for (size_t i = 0; i < current_node.InputDefs().size(); ++i) { + if (allowed_input_indices.size() > 0 && + std::find(allowed_input_indices.begin(), allowed_input_indices.end(), i) == allowed_input_indices.end()) { + continue; + } + bool fatal_error_found = false; + auto ret = CheckInputForPassThrough(gather_data_input_arg, current_node.InputDefs()[i], info, logger, + fatal_error_found, input_has_dim_1_for_axis); + if (fatal_error_found) { + LOG_DEBUG_INFO(logger, "Skip for node " + current_node.Name() + " due to input check failure at index " + + std::to_string(i)); + return false; + } else if (ret.has_value()) { + propagate_input_config[static_cast(i)] = ret.value(); + } + } + + // Make sure once Gather is moved before target node, all its outputs can be correctly be sliced. + std::unordered_map output_indices; + for (size_t i = 0; i < current_node.OutputDefs().size(); ++i) { + if (static_cast(i) == current_node_output_index) { + continue; + } + + bool fatal_error_found = false; + bool dim_1_for_axis_found = false; + auto ret = CheckInputForPassThrough(gather_data_input_arg, current_node.OutputDefs()[i], info, logger, + fatal_error_found, dim_1_for_axis_found); + if (fatal_error_found) { + LOG_DEBUG_INFO(logger, "Skip for node " + current_node.Name() + " due to output check failure at index " + + std::to_string(i)); + return false; + } else if (ret.has_value()) { + output_indices[static_cast(i)] = ret.value(); + } + } + bool output_check_success = output_indices.size() == current_node.OutputDefs().size() - 1; + + return output_check_success; +} + +bool ReductionOpPassThroughActor::PreCheck(const Graph& graph, const Node& current_node, const SliceInfo& info, + const std::vector& allowed_input_indices, + const logging::Logger& logger, + std::unordered_map& propagate_input_config, + bool& input_has_dim_1_for_axis) { + auto axis = static_cast(current_node.GetAttributes().at("axis").i()); + axis = axis < 0 ? axis + current_node.InputDefs()[0]->Shape()->dim_size() : axis; + + // Make sure layernorm/softmax's reduction happens after the axis we want to slice. + if (axis <= info.non_negative_axis) { + return false; + } + + return SimplePassThroughActor::PreCheck(graph, current_node, info, allowed_input_indices, logger, + propagate_input_config, input_has_dim_1_for_axis); +} +bool ReshapePassThroughActor::PreCheck(const Graph& graph, const Node& current_node, const SliceInfo& info, + const std::vector& /*allowed_input_indices*/, + const logging::Logger& logger, + std::unordered_map& propagate_input_config, + bool& /*input_has_dim_1_for_axis*/) { + auto data_input_shape = current_node.InputDefs()[0]->Shape(); + auto shape_input_shape = current_node.InputDefs()[1]->Shape(); + auto output_shape = current_node.OutputDefs()[0]->Shape(); + if (data_input_shape == nullptr || shape_input_shape == nullptr || shape_input_shape->dim_size() != 1 || + output_shape == nullptr) { + LOG_DEBUG_INFO(logger, "Reshape input/output node arg shape is not valid."); + return false; + } + + if (!graph_utils::IsConstantInitializer(graph, current_node.InputDefs()[1]->Name())) { + LOG_DEBUG_INFO(logger, "Skip handle the Reshape, because the new shape is not constant."); + return false; + } + + propagate_input_config.clear(); + + InlinedVector new_shape_const_values; + optimizer_utils::AppendTensorFromInitializer(graph, *current_node.InputDefs()[1], new_shape_const_values, true); + // Only below two cases are supported for easier updating shape data after propagate slice ops. + // 1). If the shape data on slicing axis is zero (e.g. remain the same after slicing), we support it. + // 2). Or if the sliced dim value is a constant, we also support it, and can update the shape data directly. + // For other cases, it is feasible to support but we don't support for now. + if (new_shape_const_values[info.non_negative_axis] == 0 || info.output_dim_on_axis.has_dim_value()) { + auto in_dims = data_input_shape->dim(); + auto out_dims = output_shape->dim(); + int in_rank = in_dims.size(); + int out_rank = out_dims.size(); + + int reshape_input_axis = -1; + // Match from left to right. + for (int i = 0; i < std::min(in_rank, out_rank); ++i) { + bool dim_value_eq = in_dims[i].has_dim_value() && out_dims[i].has_dim_value() && + in_dims[i].dim_value() == out_dims[i].dim_value(); + bool dim_param_eq = in_dims[i].has_dim_param() && out_dims[i].has_dim_param() && + in_dims[i].dim_param() == out_dims[i].dim_param(); + if (dim_value_eq || dim_param_eq) { + if (i == info.non_negative_axis) { + reshape_input_axis = i; + break; + } + continue; + } + } + + if (reshape_input_axis == -1) { + // Match from right to left. + for (int i = 0; i < std::min(in_rank, out_rank); ++i) { + int in_index = in_rank - 1 - i; + int out_index = out_rank - 1 - i; + bool dim_value_eq = in_dims[in_index].has_dim_value() && out_dims[out_index].has_dim_value() && + in_dims[in_index].dim_value() == out_dims[out_index].dim_value(); + bool dim_param_eq = in_dims[in_index].has_dim_param() && out_dims[out_index].has_dim_param() && + in_dims[in_index].dim_param() == out_dims[out_index].dim_param(); + if (dim_value_eq || dim_param_eq) { + if (out_index == info.non_negative_axis) { + reshape_input_axis = in_index; + break; + } + continue; + } + } + } + + if (reshape_input_axis == -1) { + LOG_DEBUG_INFO(logger, "Cannot find Reshape's input axis for Gather."); + return false; + } + + propagate_input_config[0] = reshape_input_axis; + return true; + } + + return false; +} + +bool ReshapePassThroughActor::PostProcess(Graph& graph, Node& current_node, int /*current_node_output_index*/, + int slice_axis, bool is_slice_scalar, bool /*input_has_dim_1_for_axis*/, + const ONNX_NAMESPACE::TensorShapeProto_Dimension& output_dim_on_axis, + const std::string& /*entry_node_name*/, + const std::unordered_map& /*new_gather_infos*/, + const logging::Logger& logger) { + LOG_DEBUG_INFO(logger, "ReshapePostProcess for Node " + current_node.Name() + "(" + current_node.OpType() + ")"); + InlinedVector new_shape_const_values; + optimizer_utils::AppendTensorFromInitializer(graph, *current_node.InputDefs()[1], new_shape_const_values, true); + + auto create_new_initializer_from_vector = [&graph](NodeArg* arg_to_be_replaced, + const InlinedVector& new_values) -> NodeArg* { + // Create new TensorProto. + ONNX_NAMESPACE::TensorProto constant_tensor_proto; + constant_tensor_proto.set_name(graph.GenerateNodeArgName(arg_to_be_replaced->Name())); + constant_tensor_proto.set_data_type(ONNX_NAMESPACE::TensorProto_DataType_INT64); + auto length = new_values.size(); + constant_tensor_proto.add_dims(length); + constant_tensor_proto.set_raw_data(new_values.data(), length * sizeof(int64_t)); + + // Add initializer into Graph. + NodeArg* new_shape_arg = &graph_utils::AddInitializer(graph, constant_tensor_proto); + // Update the output arg shape. + ONNX_NAMESPACE::TensorShapeProto new_shape; + new_shape.add_dim()->set_dim_value(length); + new_shape_arg->SetShape(new_shape); + + return new_shape_arg; + }; + + // If the shape constant on slice_axis is 0, then it keeps the original dim of input. + // If it is scalar slice, then we just remove that dim. Otherwise, we don't need to update the dim value. + if (new_shape_const_values[slice_axis] == 0) { + if (is_slice_scalar) { + LOG_DEBUG_INFO(logger, "Removing axis " + std::to_string(slice_axis) + " from shape tensor."); + NodeArg* arg_to_be_replaced = current_node.MutableInputDefs()[1]; + InlinedVector new_values; + for (int i = 0; i < static_cast(new_shape_const_values.size()); ++i) { + if (i != slice_axis) { + new_values.push_back(new_shape_const_values[i]); + } + } + auto new_shape_arg = create_new_initializer_from_vector(arg_to_be_replaced, new_values); + graph_utils::ReplaceNodeInput(current_node, 1, *new_shape_arg); + } else { + LOG_DEBUG_INFO(logger, "Reshape's shape has 0 specified for aixs: " + std::to_string(slice_axis) + + ", not need update."); + } + return true; + } + + // If it selected shape is dim value, we can update the shape tensor directory. + if (output_dim_on_axis.has_dim_value()) { + new_shape_const_values[slice_axis] = output_dim_on_axis.dim_value(); + auto new_shape_arg = create_new_initializer_from_vector(current_node.MutableInputDefs()[1], new_shape_const_values); + graph_utils::ReplaceNodeInput(current_node, 1, *new_shape_arg); + return true; + } + + ORT_THROW("Fail to update shape data in ReshapePassThroughActor::PostProcess, but this should not be called."); +} + +bool TransposePassThroughActor::PreCheck(const Graph& /*graph*/, const Node& current_node, const SliceInfo& info, + const std::vector& /*allowed_input_indices*/, + const logging::Logger& logger, + std::unordered_map& propagate_input_config, + bool& input_has_dim_1_for_axis) { + InlinedVector perm; + if (!graph_utils::GetRepeatedNodeAttributeValues(current_node, "perm", perm)) { + LOG_DEBUG_INFO(logger, "perm attribute is not set for node " + current_node.Name()); + return false; + } + propagate_input_config.clear(); + propagate_input_config[0] = static_cast(perm[info.non_negative_axis]); + input_has_dim_1_for_axis = false; + return true; +} + +bool TransposePassThroughActor::PostProcess(Graph& graph, Node& current_node, int current_node_output_index, + int slice_axis, bool is_slice_scalar, bool /*input_has_dim_1_for_axis*/, + const ONNX_NAMESPACE::TensorShapeProto_Dimension& /*output_dim_on_axis*/, + const std::string& entry_node_name, + const std::unordered_map& new_gather_infos, + const logging::Logger& logger) { + LOG_DEBUG_INFO(logger, "Enter TransposePassThroughActor::PostProcess for Node " + current_node.Name() + "(" + + current_node.OpType() + ")"); + + // We need keep the original dimension to align with original perm. + if (is_slice_scalar) { + AdaptInputAndOutputForScalarSlice(graph, current_node, current_node_output_index, slice_axis, + entry_node_name, new_gather_infos, logger); + } + return true; +} + +bool MatMulPassThroughActor::PreCheck(const Graph& /*graph*/, const Node& current_node, const SliceInfo& info, + const std::vector& allowed_input_indices, + const logging::Logger& logger, + std::unordered_map& propagate_input_config, + bool& input_has_dim_1_for_axis) { + LOG_DEBUG_INFO(logger, "Enter MatMulPassThroughActor::PreCheck for node " + current_node.Name()); + auto lhs_rank = current_node.InputDefs()[0]->Shape()->dim_size(); + auto rhs_rank = current_node.InputDefs()[1]->Shape()->dim_size(); + + if (!(lhs_rank >= 2 && rhs_rank >= 2)) { + LOG_DEBUG_INFO(logger, "MatMul input rank lower than 2, skip."); + return false; + } + + propagate_input_config.clear(); + if (info.non_negative_axis == info.input_rank - 1) { + propagate_input_config[1] = rhs_rank - 1; + return true; + } else if (info.non_negative_axis == info.input_rank - 2) { + propagate_input_config[0] = lhs_rank - 2; + return true; + } + + int target_node_output_index = optimizer_utils::IndexOfNodeOutput(current_node, *info.node_ptr->InputDefs()[0]); + const NodeArg* gather_data_input_arg = current_node.OutputDefs()[target_node_output_index]; + + input_has_dim_1_for_axis = false; + for (size_t i = 0; i < current_node.InputDefs().size(); ++i) { + if (allowed_input_indices.size() > 0 && + std::find(allowed_input_indices.begin(), allowed_input_indices.end(), i) == allowed_input_indices.end()) { + continue; + } + bool fatal_error_found = false; + auto ret = CheckInputForPassThrough(gather_data_input_arg, current_node.InputDefs()[i], info, logger, + fatal_error_found, input_has_dim_1_for_axis); + if (fatal_error_found) { + LOG_DEBUG_INFO(logger, "Skip for node " + current_node.Name() + " due to input check failure at index " + + std::to_string(i)); + return false; + } else if (ret.has_value()) { + LOG_DEBUG_INFO(logger, "Add new input candidate for node " + current_node.Name() + " at index " + + std::to_string(i) + " with axis " + std::to_string(ret.value())); + propagate_input_config[static_cast(i)] = ret.value(); + } + } + + return propagate_input_config.size() > 0; +} + +bool MatMulPassThroughActor::PostProcess(Graph& graph, Node& current_node, int current_node_output_index, + int slice_axis, bool is_slice_scalar, bool /*input_has_dim_1_for_axis*/, + const ONNX_NAMESPACE::TensorShapeProto_Dimension& /*output_dim_on_axis*/, + const std::string& entry_node_name, + const std::unordered_map& new_gather_infos, + const logging::Logger& logger) { + LOG_DEBUG_INFO(logger, "Enter MatMulPassThroughActor::PostProcess for Node " + current_node.Name() + "(" + + current_node.OpType() + ")"); + + // We need keep the original dimension to avoid the matmul inputs cannot be compatible to compute. + if (is_slice_scalar) { + AdaptInputAndOutputForScalarSlice(graph, current_node, current_node_output_index, slice_axis, + entry_node_name, new_gather_infos, logger); + } + return true; +} + +} // namespace onnxruntime::optimizer::compute_optimizer + +#endif diff --git a/onnxruntime/core/optimizer/compute_optimizer/passthrough_actors.h b/onnxruntime/core/optimizer/compute_optimizer/passthrough_actors.h new file mode 100644 index 0000000000..a2a5719179 --- /dev/null +++ b/onnxruntime/core/optimizer/compute_optimizer/passthrough_actors.h @@ -0,0 +1,333 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#ifdef ENABLE_TRAINING +#pragma once + +// Uncomment for debugging +// #define NEED_LOG_DEBUG_INFO 1 + +#ifdef NEED_LOG_DEBUG_INFO +#define LOG_DEBUG_INFO(logger, message) LOGS(logger, WARNING) << message +#else +#define LOG_DEBUG_INFO(logger, message) \ + ORT_UNUSED_PARAMETER(logger); \ + do { \ + } while (0) +#endif + +namespace onnxruntime::optimizer::compute_optimizer { + +/** + * @brief Struct to hold the information of the slicing operations. + * + * Initially, an instance of this class for entry node is created, as the slice op propagates to entry node's inputs, + * more instances of this class are created. The propagation stops when the all inputs are not supported to be sliced. + */ +struct SliceInfo { + static constexpr int kSliceDataInputIndex = 0; + static constexpr int kSliceOutputIndex = 0; + + SliceInfo(Node* slice_node, + bool is_slice_scalar, + const std::string& slice_axis_attr_name, + int slice_axis, + bool is_entry_node_ptr = false) + : node_ptr(slice_node), is_scalar_slice(is_slice_scalar) { + axis_attr_name = slice_axis_attr_name; + + const NodeArg* input = node_ptr->InputDefs()[kSliceDataInputIndex]; + const NodeArg* output = node_ptr->OutputDefs()[kSliceOutputIndex]; + input_rank = input->Shape()->dim_size(); + non_negative_axis = slice_axis < 0 ? input_rank + slice_axis : slice_axis; + + if (!is_scalar_slice) { + output_dim_on_axis = output->Shape()->dim(non_negative_axis); + } + + if (is_entry_node_ptr) { + entry_slice_arg_name = node_ptr->OutputDefs()[kSliceOutputIndex]->Name(); + } + } + + int GetDataInputIndex() const { + return kSliceDataInputIndex; + } + + int GetOutputIndex() const { + return kSliceOutputIndex; + } + + Node* node_ptr; // The Gather/GatherND node that triggers the optimization search. + bool is_scalar_slice; // whether the slice is a scalar, if it is, after Gather, rank will be reduced by 1. + std::string axis_attr_name; + int non_negative_axis; // The axis to slice on + std::string entry_slice_arg_name; + + int input_rank; // rank of the Gather data input tensor + + // The dimension of the output tensor on the slicing axis + // Be noted: if it is a scalar slicing, this dim will not be set, which means, afterward when use it to update + // shapes, that dim at axis will be removed. + ONNX_NAMESPACE::TensorShapeProto_Dimension output_dim_on_axis; +}; + +/** + * @brief Base class for all pass through actors. + * + * Each actors defines rules to determine whether a node can be passed through, and how to do the pass through. + * PreCheck is the interface to check whether a node can be passed through. + * The pass through is done transparently, without any interface required to implemented. + * PostProcess is the interface to do some adaptor work after the pass through. + */ +class OperatorPassThroughActorBase { + public: + OperatorPassThroughActorBase() = default; + virtual ~OperatorPassThroughActorBase() = default; + + /** + * @brief Check whether a node can be passed through. + * At this point, graph modification is not started, once we see any clues that this node cannot be passed through, + * We should return false immediately. + * + * @param graph The graph that the node belongs to. + * @param current_node The node to be checked. + * @param info The slicing info of the Gather/GatherND node. + * @param allowed_input_indices The input indices explicitly specified of the current_node that are allowed to do pass + * through. + * @param propagate_input_config: Used as a return value - a map of input index to new slice axis. + * The key is an integer, which is the index of the input of the current_node. + * The value is an integer, which is the new axis index after the pass through on the corresponding input. + * For example: + * > if the current_node is a Add node, and the slice axe is 1, then the corresponding input should + * also have axis 1 when we move the slice to the input. + * > if the current_node is a Transpose (perm=[1, 0, 2]) node, and the slice + * axis is 1, then the new axis for the input should be 0. + * @param input_has_dim_1_for_axis: Used as a return value - a bool indicates whether any of current_node' input + * has dim 1 on the slice axis. + */ + virtual bool PreCheck(const Graph& graph, const Node& current_node, const SliceInfo& info, + const std::vector& allowed_input_indices, + const logging::Logger& logger, + std::unordered_map& propagate_input_config, + bool& input_has_dim_1_for_axis) = 0; + + /** + * @brief After slice op pass through all inputs, do some post process work. + * + * Be noted: at this point, slice op is already removed, so we cannot access SliceInfo any more, instead, + * we pass important infos including slice_axis, input_rank, is_scalar_slice, etc as parameters of this function. + * + * @param graph The graph that the node belongs to. + * @param current_node The node that has been passed through. + * @param current_node_output_index The output index of the current_node connecting to slice op. + * @param slice_axis slice axis of the slice op. + * @param is_slice_scalar whether the slice is a scalar. + * @param input_has_dim_1_for_axis whether any of current_node's inputs has dim 1 on the slice axis. + * @param output_dim_on_axis dimension of the slice op's output tensor on the slice axis. + * @param entry_node_name name of entry node that trigger the pass through search, for naming only. + * @param new_gather_infos new gather infos that are generated during the pass through for current_node's inputs. + * @param logger + * @return + */ + virtual bool PostProcess(Graph& graph, Node& current_node, int current_node_output_index, + int slice_axis, bool is_slice_scalar, bool input_has_dim_1_for_axis, + const ONNX_NAMESPACE::TensorShapeProto_Dimension& output_dim_on_axis, + const std::string& entry_node_name, + const std::unordered_map& new_gather_infos, + const logging::Logger& logger) = 0; +}; + +class DefaultOperatorPassThroughActorBase : public OperatorPassThroughActorBase { + public: + DefaultOperatorPassThroughActorBase() = default; + ~DefaultOperatorPassThroughActorBase() = default; + + bool PreCheck(const Graph&, const Node&, const SliceInfo&, const std::vector&, const logging::Logger&, + std::unordered_map&, bool&) override { + return true; + }; + + bool PostProcess(Graph& graph, Node& current_node, int current_node_output_index, + int slice_axis, bool is_slice_scalar, bool input_has_dim_1_for_axis, + const ONNX_NAMESPACE::TensorShapeProto_Dimension& output_dim_on_axis, + const std::string& entry_node_name, + const std::unordered_map& new_gather_infos, + const logging::Logger& logger) override; +}; + +class SimplePassThroughActor : public DefaultOperatorPassThroughActorBase { + public: + SimplePassThroughActor() = default; + ~SimplePassThroughActor() = default; + + bool PreCheck(const Graph& graph, const Node& current_node, const SliceInfo& info, + const std::vector& allowed_input_indices, + const logging::Logger& logger, + std::unordered_map& propagate_input_config, + bool& input_has_dim_1_for_axis) override; +}; + +class ReductionOpPassThroughActor : public SimplePassThroughActor { + public: + ReductionOpPassThroughActor() = default; + ~ReductionOpPassThroughActor() = default; + + bool PreCheck(const Graph& graph, const Node& current_node, const SliceInfo& info, + const std::vector& allowed_input_indices, + const logging::Logger& logger, + std::unordered_map& propagate_input_config, + bool& input_has_dim_1_for_axis) override; +}; + +class ReshapePassThroughActor : public DefaultOperatorPassThroughActorBase { + public: + ReshapePassThroughActor() = default; + ~ReshapePassThroughActor() = default; + + bool PreCheck(const Graph& graph, const Node& current_node, const SliceInfo& info, + const std::vector& allowed_input_indices, + const logging::Logger& logger, + std::unordered_map& propagate_input_config, + bool& input_has_dim_1_for_axis) override; + + // Once slice node is passed through, we need to update the shape accordingly. + bool PostProcess(Graph& graph, Node& current_node, int current_node_output_index, + int slice_axis, bool is_slice_scalar, bool input_has_dim_1_for_axis, + const ONNX_NAMESPACE::TensorShapeProto_Dimension& output_dim_on_axis, + const std::string& entry_node_name, + const std::unordered_map& new_gather_infos, + const logging::Logger& logger) override; +}; + +class TransposePassThroughActor : public DefaultOperatorPassThroughActorBase { + public: + TransposePassThroughActor() = default; + ~TransposePassThroughActor() = default; + + bool PreCheck(const Graph& graph, const Node& current_node, const SliceInfo& info, + const std::vector& allowed_input_indices, + const logging::Logger& logger, + std::unordered_map& propagate_input_config, + bool& input_has_dim_1_for_axis) override; + + // If scalar slice happens, we need adapt the input, otherwise the perm cannot be matched. + bool PostProcess(Graph& graph, Node& current_node, int current_node_output_index, + int slice_axis, bool is_slice_scalar, bool input_has_dim_1_for_axis, + const ONNX_NAMESPACE::TensorShapeProto_Dimension& output_dim_on_axis, + const std::string& entry_node_name, + const std::unordered_map& new_gather_infos, + const logging::Logger& logger) override; +}; + +class MatMulPassThroughActor : public DefaultOperatorPassThroughActorBase { + public: + MatMulPassThroughActor() = default; + ~MatMulPassThroughActor() = default; + + // Check which inputs can be propagated according to the slice axis. + bool PreCheck(const Graph& graph, const Node& current_node, const SliceInfo& info, + const std::vector& allowed_input_indices, + const logging::Logger& logger, + std::unordered_map& propagate_input_config, + bool& input_has_dim_1_for_axis) override; + + // If scalar slice happens in the second last dimension, we need to adapt the input. + bool PostProcess(Graph& graph, Node& current_node, int current_node_output_index, + int slice_axis, bool is_slice_scalar, bool input_has_dim_1_for_axis, + const ONNX_NAMESPACE::TensorShapeProto_Dimension& output_dim_on_axis, + const std::string& entry_node_name, + const std::unordered_map& new_gather_infos, + const logging::Logger& logger) override; +}; + +/** + * @brief Update the dim value using given new dim value at specified axis. + * + * @param arg_to_update The NodeArg to be updated. + * @param reverse_axis A negative axis MUST be given here. This is to make sure if arg_to_update has less rank + * than expected value, the update will be ignored. + * @param output_dim_on_axis New dim value to be updated. + * @return true if the update is done. + */ +bool UpdateSliceOutputShape(NodeArg& arg_to_update, int reverse_axis, + const ONNX_NAMESPACE::TensorShapeProto_Dimension& new_dim_value); + +/** + * @brief Insert a new node to the graph, + * 1. taking dest_node.input[dest_input_index] as the input of the new node. + * 2. remove connection of dest_node and it's dest_input_index-th input producer node. + * 3. connect the new node and dest_node. + * + * Original graph: + * Node A + * / \ + * A-output-0 A-output-1 + * \ B-input-1 + * \ / + * Node B + * | + * + * dest_node = Node B + * dest_input_index = 0 + * op_type = C + * + * After inserting the new node: + * Node A + * / \ + * A-output-0 A-output-1 + * \ + * Node C + * / \ + * c-output-0 C-output-1 B-input-1 + * \ / + * Node B + * | + * @param graph Graph to insert the new node. + * @param dest_node The node to insert the new node before. + * @param dest_in_index The input index of the dest_node to insert the new node before. + * @param new_node_output_index The output index of the new node to connect to the dest_node. + * @param name The name of the new node. + * @param op_type The op_type of the new node. + * @param description The description of the new node. + * @param input_args The input args of the new node. At least one of the input args should be the + * dest_node's dest_in_index-th input arg. + * @param attributes The attributes of the new node. + * @param domain The domain of the new node. + * @param logger The logger. + * @return + */ +Node* InsertIntermediateNodeOnDestInput(Graph& graph, + Node& dest_node, int dest_in_index, + int new_node_input_index, + int new_node_output_index, + const std::string& name, const std::string& op_type, + const std::string& description, + const InlinedVector& input_args, + const InlinedVector& output_args, + const onnxruntime::NodeAttributes& attributes, + const std::string& domain, + const logging::Logger& logger); + +/** + * @brief Insert adaptor nodes for the inputs and output, to make sure they remain the same rank, when scalar slicing + * is done. + * + * Be noted: at this point, slice node already been removed. + * + * @param graph Graph to insert the adaptor nodes. + * @param current_node For whom to insert the adaptor nodes. + * @param slice_axis The axis of the slice node. + * @param entry_node_name Then name of the entry slice node, used for naming only. + * @param new_gather_infos Populated slicing infos for current_node's inputs. + * @param target_node_output_index output_index of current_node's output, connecting to the slice node. + * @param logger Logger. + */ +void AdaptInputAndOutputForScalarSlice(Graph& graph, Node& current_node, int current_node_output_index, + int slice_axis, const std::string& entry_node_name, + const std::unordered_map& new_gather_infos, + const logging::Logger& logger); + +} // namespace onnxruntime::optimizer::compute_optimizer + +#endif diff --git a/onnxruntime/core/optimizer/graph_transformer_utils.cc b/onnxruntime/core/optimizer/graph_transformer_utils.cc index 2231eac0bd..8d76a160b7 100644 --- a/onnxruntime/core/optimizer/graph_transformer_utils.cc +++ b/onnxruntime/core/optimizer/graph_transformer_utils.cc @@ -307,7 +307,7 @@ InlinedVector> GenerateTransformers( #ifdef ENABLE_TRAINING // Put memory optimization transformer at last (which is done after most of fusions are done) by intention. - // Known issue: after mmeory optimization is completed, if some fusion happens, it is possible that the + // Known issue: after memory optimization is completed, if some fusion happens, it is possible that the // node priority got changed. This may disorder the execution order of nodes to recompute. // TODO(pengwa): need to fix this issue. const std::string enable_memory_optimizer = @@ -329,7 +329,7 @@ InlinedVector> GenerateTransformers( transformers.emplace_back(std::make_unique(std::move(cpu_allocator))); // NCHWCtransformer should have a higher priority versus this. Because NCHWCtransformer also do the similar things // of fusion patterns and target on CPU. However, NCHWCtransformer will reorder the layout to nchwc which is only available for - // x86-64 cpu, not edge cpu like arm. But This tranformer could be used by opencl-ep/cpu-ep. So + // x86-64 cpu, not edge cpu like arm. But This transformer could be used by opencl-ep/cpu-ep. So // we will prefer NhwcTransformer once ort runs on x86-64 CPU, otherwise ConvAddActivationFusion is enabled. // PR #6351 implemented similar fusion-pattern for CUDA only, and can only fuse conv-add-relu, // while we can fuse more activation. diff --git a/onnxruntime/test/optimizer/compute_optimizer_test.cc b/onnxruntime/test/optimizer/compute_optimizer_test.cc new file mode 100644 index 0000000000..a9f1fd705d --- /dev/null +++ b/onnxruntime/test/optimizer/compute_optimizer_test.cc @@ -0,0 +1,1596 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#ifdef ENABLE_TRAINING + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4244) +#endif + +#include +#include "core/graph/onnx_protobuf.h" + +#include "gtest/gtest.h" +#include "gmock/gmock.h" + +#include "asserts.h" +#include "core/common/span_utils.h" +#include "core/framework/data_types.h" +#include "core/framework/ort_value.h" +#include "core/graph/graph_utils.h" +#include "core/graph/graph_viewer.h" +#include "core/graph/model.h" + +#include "core/optimizer/common_subexpression_elimination.h" +#include "core/optimizer/compute_optimizer/compute_optimizer.h" +#include "core/optimizer/utils.h" +#include "core/platform/env.h" +#include "core/session/inference_session.h" +#include "core/util/math.h" + +#include "test/compare_ortvalue.h" +#include "test/framework/test_utils.h" +#include "test/providers/provider_test_utils.h" +#include "test/test_environment.h" +#include "test/util/include/temp_dir.h" +#include "test/util/include/asserts.h" +#include "test/util/include/default_providers.h" + +namespace onnxruntime { +namespace test { + +#define MODEL_FOLDER ORT_TSTR("testdata/transform/") + +// LayerNormalization/Gelu implementation are in contrib namespace (OnnxDomain 1), so +// Without contib_ops enabled, we cannot parse the graph correctly. +#ifndef DISABLE_CONTRIB_OPS +static void GatherNDComputationReductionTest(const std::string& op_type, + const logging::Logger& logger, + std::function validation_func) { + std::string op_type_lower = op_type; + std::transform(op_type_lower.begin(), op_type_lower.end(), op_type_lower.begin(), + [](unsigned char c) { return std::tolower(c); }); + std::string file_path = std::string("testdata/transform/computation_reduction/gathernd/gathernd_") + op_type_lower + + std::string(".onnx"); + std::shared_ptr model; + ASSERT_STATUS_OK(Model::Load(ToPathString(file_path), model, nullptr, logger)); + Graph& graph = model->MainGraph(); + std::map op_to_count = CountOpsInGraph(graph); + + onnxruntime::GraphTransformerManager graph_transformation_mgr{1}; + ASSERT_STATUS_OK(graph_transformation_mgr.Register(std::make_unique(), TransformerLevel::Level1)); + ASSERT_STATUS_OK(graph_transformation_mgr.ApplyTransformers(graph, TransformerLevel::Level1, logger)); + + validation_func(graph, op_type); +} + +void SingleOpDefaultValidationFunc(Graph& graph, std::string op_type) { + GraphViewer graph_viewer(graph); + const auto& node_topology_list = graph_viewer.GetNodesInTopologicalOrder(); + + Node* gathernd_node = nullptr; + for (auto node_index : node_topology_list) { + Node* p_node = graph.GetNode(node_index); + ASSERT_FALSE(p_node == nullptr); + if (p_node->OpType().compare("GatherND") == 0) { + gathernd_node = p_node; + EXPECT_EQ(gathernd_node->MutableInputDefs()[0]->Name(), "input"); + const auto& consumers = graph.GetConsumerNodes(gathernd_node->MutableOutputDefs()[0]->Name()); + EXPECT_EQ(consumers[0]->OpType(), op_type); + } + } + + ASSERT_FALSE(gathernd_node == nullptr); +} + +TEST(ComputeOptimizerTests, GatherND_Gelu) { + const logging::Logger* logger = &logging::LoggingManager::DefaultLogger(); + GatherNDComputationReductionTest("Gelu", *logger, SingleOpDefaultValidationFunc); +} + +TEST(ComputeOptimizerTests, GatherND_Add) { + const logging::Logger* logger = &logging::LoggingManager::DefaultLogger(); + GatherNDComputationReductionTest("Add", *logger, [](Graph& graph, std::string op_type) -> void { + GraphViewer graph_viewer(graph); + const auto& node_topology_list = graph_viewer.GetNodesInTopologicalOrder(); + + Node* gathernd_node = nullptr; + bool found_gathernd_around_graph_output = false; + for (auto node_index : node_topology_list) { + Node* p_node = graph.GetNode(node_index); + ASSERT_FALSE(p_node == nullptr); + if (p_node->OpType().compare("GatherND") == 0) { + if (p_node->OutputDefs()[0]->Name().compare("output") != 0) { + gathernd_node = p_node; + EXPECT_EQ(gathernd_node->MutableInputDefs()[0]->Name(), "input"); + const auto& consumers = graph.GetConsumerNodes(gathernd_node->MutableOutputDefs()[0]->Name()); + EXPECT_EQ(consumers[0]->OpType(), op_type); + } else { + found_gathernd_around_graph_output = true; + } + } + } + ASSERT_FALSE(gathernd_node == nullptr); + EXPECT_TRUE(found_gathernd_around_graph_output); }); +} + +TEST(ComputeOptimizerTests, GatherND_LayerNormalization) { + const logging::Logger* logger = &logging::LoggingManager::DefaultLogger(); + GatherNDComputationReductionTest("LayerNormalization", *logger, SingleOpDefaultValidationFunc); +} + +TEST(ComputeOptimizerTests, GatherND_MatMul) { + const logging::Logger* logger = &logging::LoggingManager::DefaultLogger(); + GatherNDComputationReductionTest("MatMul", *logger, SingleOpDefaultValidationFunc); +} + +/** + * @brief Class represent a input data (dimensions, data type and value). + */ +struct TestInputData { + template + TestInputData(const std::string& name, const TensorShapeVector& dims, const std::vector& values) + : name_(name), dims_(dims), values_(values) {} + + OrtValue ToOrtValue() { + OrtValue ortvalue; + std::vector dims; + dims.reserve(dims_.size()); + dims.insert(dims.end(), dims_.begin(), dims_.end()); + std::visit([&ortvalue, &dims](auto&& arg) { + using T = std::decay_t; + if constexpr (std::is_same_v> || + std::is_same_v> || + std::is_same_v>) + CreateMLValue( + TestCPUExecutionProvider()->GetAllocator(0, OrtMemTypeDefault), dims, arg, &ortvalue); + else + static_assert("Unspported types!"); + }, + values_); + + return ortvalue; + } + + std::string GetName() const { + return name_; + } + + private: + std::string name_; + TensorShapeVector dims_; + std::variant, std::vector, std::vector> values_; +}; + +void RandomFillFloatVector(const TensorShapeVector& shape, std::vector& data) { + float scale = 1.f; + float mean = 0.f; + float seed = 123.f; + data.resize(TensorShape(shape).Size()); + std::default_random_engine generator_float{gsl::narrow_cast(seed)}; + std::normal_distribution distribution_float{mean, scale}; + + std::for_each(data.begin(), data.end(), + [&generator_float, &distribution_float](float& value) { + value = distribution_float(generator_float); + }); +} + +void RandomFillHalfVector(const TensorShapeVector& shape, std::vector& data) { + std::vector data_float(TensorShape(shape).Size()); + std::transform(data_float.begin(), data_float.end(), data.begin(), + [](float value) { return MLFloat16(math::floatToHalf(value)); }); +} + +struct InputContainer { + InputContainer() = default; + + template + TestInputData& AddInput(const std::string& name, const TensorShapeVector dims, const std::vector& values) { + inputs_.emplace_back(TestInputData(name, dims, values)); + return inputs_.back(); + } + + template + TestInputData& AddInput(const std::string& name, TensorShapeVector dims, + std::function< + void(const TensorShapeVector& shape, std::vector& data)> + func = nullptr) { + std::vector values(TensorShape(dims).Size()); + if (func) { + func(dims, values); + } + + inputs_.emplace_back(TestInputData(name, dims, values)); + return inputs_.back(); + } + + void ToInputMap(NameMLValMap& feeds) const { + for (auto input : inputs_) { + feeds.insert({input.GetName(), input.ToOrtValue()}); + } + } + + private: + std::vector inputs_; +}; + +static void RunModelWithData(const PathString& model_uri, const std::string session_log_id, + const std::string& provider_type, const InputContainer& input_container, + const std::vector& output_names, + std::vector& run_results) { + SessionOptions so; + // we don't want any transformation here. + so.graph_optimization_level = TransformerLevel::Default; + so.session_logid = session_log_id; + + InferenceSession session_object{so, GetEnvironment()}; + std::unique_ptr execution_provider; + if (provider_type == onnxruntime::kCpuExecutionProvider) + execution_provider = DefaultCpuExecutionProvider(); + else if (provider_type == onnxruntime::kCudaExecutionProvider) + execution_provider = DefaultCudaExecutionProvider(); + else if (provider_type == onnxruntime::kRocmExecutionProvider) + execution_provider = DefaultRocmExecutionProvider(); + EXPECT_TRUE(session_object.RegisterExecutionProvider(std::move(execution_provider)).IsOK()); + + Status st; + ASSERT_TRUE((st = session_object.Load(model_uri)).IsOK()) << st.ErrorMessage(); + ASSERT_TRUE((st = session_object.Initialize()).IsOK()) << st.ErrorMessage(); + + NameMLValMap feeds; + input_container.ToInputMap(feeds); + + // Now run + RunOptions run_options; + st = session_object.Run(run_options, feeds, output_names, &run_results); + + ASSERT_TRUE(st.IsOK()) << "RunModelWithData run graph failed with error: " << st.ErrorMessage(); +} + +TEST(ComputeOptimizerTests, GatherND_E2E) { + const logging::Logger* logger = &logging::LoggingManager::DefaultLogger(); + auto model_uri = MODEL_FOLDER "computation_reduction/gathernd/e2e.onnx"; + std::shared_ptr model; + ASSERT_STATUS_OK(Model::Load(model_uri, model, nullptr, *logger)); + Graph& graph = model->MainGraph(); + std::map op_to_count = CountOpsInGraph(graph); + + onnxruntime::GraphTransformerManager graph_transformation_mgr{5}; + ASSERT_STATUS_OK(graph_transformation_mgr.Register(std::make_unique(), TransformerLevel::Level1)); + ASSERT_STATUS_OK(graph_transformation_mgr.ApplyTransformers(graph, TransformerLevel::Level1, *logger)); + + // check the expected node orders. + { + GraphViewer graph_viewer(graph); + const auto& node_topology_list = graph_viewer.GetNodesInTopologicalOrder(); + + Node* gathernd_node = nullptr; + for (auto node_index : node_topology_list) { + Node* p_node = graph.GetNode(node_index); + ASSERT_FALSE(p_node == nullptr); + if (p_node->OpType().compare("GatherND") == 0) { + gathernd_node = p_node; + const Node* layer_norm_node = graph.GetProducerNode(gathernd_node->MutableInputDefs()[0]->Name()); + EXPECT_EQ(layer_norm_node->OpType(), "LayerNormalization"); + EXPECT_EQ(layer_norm_node->Name(), "layer_norm_1"); + const auto& consumers = graph.GetConsumerNodes(gathernd_node->MutableOutputDefs()[0]->Name()); + EXPECT_EQ(consumers[0]->OpType(), "MatMul"); + EXPECT_EQ(consumers[0]->Name(), "matmul_1"); + break; + } + } + + ASSERT_FALSE(gathernd_node == nullptr); + } + + // check result diff after the re-order + onnxruntime::test::TemporaryDirectory tmp_dir{ORT_TSTR("compute_optimizer_test_tmp_dir")}; + PathString new_model_uri{ConcatPathComponent(tmp_dir.Path(), + ORT_TSTR("computation_reduction_transformer_after.onnx"))}; + ASSERT_STATUS_OK(Model::Save(*model, new_model_uri)); + + InputContainer input_container; + + int batch_size = 8; + int sequence = 128; + int hidden_size = 128; + int dynamic_predict_count = 20; + input_container.AddInput("input", {batch_size, sequence, hidden_size}, RandomFillFloatVector); + + const TensorShapeVector dims_unsqueezed_masked_lm_positions{batch_size, dynamic_predict_count, 1}; + std::vector values_unsqueezed_masked_lm_positions(TensorShape(dims_unsqueezed_masked_lm_positions).Size()); + + std::random_device rd; // obtain a random number from hardware + std::mt19937 eng(rd()); // seed the generator + std::uniform_int_distribution<> distr(0, sequence - 1); // define the range + std::for_each(values_unsqueezed_masked_lm_positions.begin(), values_unsqueezed_masked_lm_positions.end(), + [&distr, &eng](int64_t& value) { value = distr(eng); }); + + input_container.AddInput("unsqueezed_masked_lm_positions", + dims_unsqueezed_masked_lm_positions, + values_unsqueezed_masked_lm_positions); + + static const std::string all_provider_types[] = { + onnxruntime::kCpuExecutionProvider, +#ifdef USE_CUDA + onnxruntime::kCudaExecutionProvider, +#elif USE_ROCM + onnxruntime::kRocmExecutionProvider, +#endif + }; + const std::vector output_names{"output", "gather_output"}; + + for (auto& provider_type : all_provider_types) { + std::vector expected_ort_values; + RunModelWithData(model_uri, std::string("RawGraphRun"), provider_type, + input_container, output_names, expected_ort_values); + + std::vector actual_ort_values; + RunModelWithData(ToPathString(new_model_uri), std::string("OptimizedGraphRun"), provider_type, + input_container, output_names, actual_ort_values); + + ASSERT_TRUE(expected_ort_values.size() == actual_ort_values.size()); + constexpr double per_sample_tolerance = 1e-4; + constexpr double relative_per_sample_tolerance = 1e-4; + for (size_t i = 0; i < expected_ort_values.size(); i++) { + auto ret = CompareOrtValue(actual_ort_values[i], expected_ort_values[i], + per_sample_tolerance, relative_per_sample_tolerance, false); + EXPECT_EQ(ret.first, COMPARE_RESULT::SUCCESS) << ret.second; + } + } +} + +TEST(ComputeOptimizerTests, GatherMatMul_ScalarSlicingOnBatchDim) { + const logging::Logger* logger = &logging::LoggingManager::DefaultLogger(); + auto model_uri = MODEL_FOLDER "computation_reduction/gather/gather_matmul_scalar_batch_dim.onnx"; + std::shared_ptr model; + ASSERT_STATUS_OK(Model::Load(model_uri, model, nullptr, *logger)); + Graph& graph = model->MainGraph(); + std::map op_to_count = CountOpsInGraph(graph); + + onnxruntime::GraphTransformerManager graph_transformation_mgr{1}; + ASSERT_STATUS_OK(graph_transformation_mgr.Register(std::make_unique(), TransformerLevel::Level1)); + ASSERT_STATUS_OK(graph_transformation_mgr.ApplyTransformers(graph, TransformerLevel::Level1, *logger)); + + GraphViewer graph_viewer(graph); + // Check the first Gather. + { + const std::vector& consumers = graph.GetConsumerNodes("input1"); + ASSERT_EQ(consumers.size(), 1U); + const Node* gather_node = consumers[0]; + ASSERT_EQ(gather_node->OpType(), "Gather"); + + auto& attrs = gather_node->GetAttributes(); + ASSERT_TRUE(attrs.find("axis") != attrs.end()); + + auto& axis_attr = attrs.at("axis"); + auto axis_value = (int)axis_attr.i(); + ASSERT_EQ(axis_value, 0); + } + + // Check the second Gather. + { + const std::vector& consumers = graph.GetConsumerNodes("input2"); + ASSERT_EQ(consumers.size(), 1U); + const Node* gather_node = consumers[0]; + ASSERT_EQ(gather_node->OpType(), "Gather"); + + auto& attrs = gather_node->GetAttributes(); + ASSERT_TRUE(attrs.find("axis") != attrs.end()); + + auto& axis_attr = attrs.at("axis"); + auto axis_value = (int)axis_attr.i(); + ASSERT_EQ(axis_value, 0); + } + + // Check MatMul's input and output. + { + const Node* m5 = graph.GetProducerNode("m1_out"); + ASSERT_FALSE(m5 == nullptr); + EXPECT_EQ(m5->OpType(), "MatMul"); + EXPECT_EQ(m5->Name(), "m1"); + + const Node* lhs_input = graph.GetProducerNode(m5->InputDefs()[0]->Name()); + const Node* rhs_input = graph.GetProducerNode(m5->InputDefs()[1]->Name()); + + ASSERT_FALSE(lhs_input == nullptr); + EXPECT_EQ(lhs_input->OpType(), "Unsqueeze"); + + ASSERT_FALSE(rhs_input == nullptr); + EXPECT_EQ(rhs_input->OpType(), "Unsqueeze"); + } + + // Check result diff after the re-order + onnxruntime::test::TemporaryDirectory tmp_dir{ORT_TSTR("compute_optimizer_test_tmp_dir")}; + PathString new_model_uri{ConcatPathComponent(tmp_dir.Path(), + ORT_TSTR("gather_matmul_scalar_batch_dim_optimized.onnx"))}; + ASSERT_STATUS_OK(Model::Save(*model, new_model_uri)); + + int64_t batch_size = 8; + int64_t sequence_length = 16; + int64_t hidden_size = 1024; + + InputContainer input_container; + + input_container.AddInput("input1", {batch_size, sequence_length, hidden_size}, RandomFillFloatVector); + input_container.AddInput("input2", {batch_size, hidden_size, sequence_length}, RandomFillFloatVector); + + static const std::string all_provider_types[] = { + onnxruntime::kCpuExecutionProvider, +#ifdef USE_CUDA + onnxruntime::kCudaExecutionProvider, +#elif USE_ROCM + onnxruntime::kRocmExecutionProvider, +#endif + }; + + const std::vector output_names = {"final_output"}; + + for (auto& provider_type : all_provider_types) { + std::vector expected_ort_values; + RunModelWithData(model_uri, std::string("RawGraphRun"), provider_type, + input_container, output_names, expected_ort_values); + + std::vector actual_ort_values; + RunModelWithData(ToPathString(new_model_uri), std::string("OptimizedGraphRun"), + provider_type, input_container, output_names, actual_ort_values); + + ASSERT_TRUE(expected_ort_values.size() == actual_ort_values.size()); + constexpr double per_sample_tolerance = 1e-4; + constexpr double relative_per_sample_tolerance = 1e-4; + for (size_t i = 0; i < expected_ort_values.size(); i++) { + auto ret = CompareOrtValue(actual_ort_values[i], expected_ort_values[i], + per_sample_tolerance, relative_per_sample_tolerance, false); + EXPECT_EQ(ret.first, COMPARE_RESULT::SUCCESS) << ret.second; + } + } +} + +TEST(ComputeOptimizerTests, GatherMatMul_SlicingOnBatchDim) { + const logging::Logger* logger = &logging::LoggingManager::DefaultLogger(); + auto model_uri = MODEL_FOLDER "computation_reduction/gather/gather_matmul_batch_dim.onnx"; + std::shared_ptr model; + ASSERT_STATUS_OK(Model::Load(model_uri, model, nullptr, *logger)); + Graph& graph = model->MainGraph(); + std::map op_to_count = CountOpsInGraph(graph); + + onnxruntime::GraphTransformerManager graph_transformation_mgr{1}; + ASSERT_STATUS_OK(graph_transformation_mgr.Register(std::make_unique(), TransformerLevel::Level1)); + ASSERT_STATUS_OK(graph_transformation_mgr.ApplyTransformers(graph, TransformerLevel::Level1, *logger)); + + GraphViewer graph_viewer(graph); + // Check the first Gather. + { + const std::vector& consumers = graph.GetConsumerNodes("input1"); + ASSERT_EQ(consumers.size(), 1U); + const Node* gather_node = consumers[0]; + ASSERT_EQ(gather_node->OpType(), "Gather"); + + auto& attrs = gather_node->GetAttributes(); + ASSERT_TRUE(attrs.find("axis") != attrs.end()); + + auto& axis_attr = attrs.at("axis"); + auto axis_value = (int)axis_attr.i(); + ASSERT_EQ(axis_value, 0); + } + + // Check the second Gather. + { + const std::vector& consumers = graph.GetConsumerNodes("input2"); + ASSERT_EQ(consumers.size(), 1U); + const Node* gather_node = consumers[0]; + ASSERT_EQ(gather_node->OpType(), "Gather"); + + auto& attrs = gather_node->GetAttributes(); + ASSERT_TRUE(attrs.find("axis") != attrs.end()); + + auto& axis_attr = attrs.at("axis"); + auto axis_value = (int)axis_attr.i(); + ASSERT_EQ(axis_value, 0); + } + + // Check MatMul's input and output. + { + const Node* m5 = graph.GetProducerNode("m1_out"); + ASSERT_FALSE(m5 == nullptr); + EXPECT_EQ(m5->OpType(), "MatMul"); + EXPECT_EQ(m5->Name(), "m1"); + + const Node* lhs_input = graph.GetProducerNode(m5->InputDefs()[0]->Name()); + const Node* rhs_input = graph.GetProducerNode(m5->InputDefs()[1]->Name()); + + ASSERT_FALSE(lhs_input == nullptr); + EXPECT_EQ(lhs_input->OpType(), "Gather"); + + ASSERT_FALSE(rhs_input == nullptr); + EXPECT_EQ(rhs_input->OpType(), "Gather"); + } + + // Check result diff after the re-order + onnxruntime::test::TemporaryDirectory tmp_dir{ORT_TSTR("compute_optimizer_test_tmp_dir")}; + PathString new_model_uri{ConcatPathComponent(tmp_dir.Path(), + ORT_TSTR("gather_matmul_batch_dim_optimized.onnx"))}; + ASSERT_STATUS_OK(Model::Save(*model, new_model_uri)); + + int64_t batch_size = 8; + int64_t sequence_length = 16; + int64_t hidden_size = 1024; + + InputContainer input_container; + + input_container.AddInput("input1", {batch_size, sequence_length, hidden_size}, RandomFillFloatVector); + input_container.AddInput("input2", {batch_size, hidden_size, sequence_length}, RandomFillFloatVector); + + static const std::string all_provider_types[] = { + onnxruntime::kCpuExecutionProvider, +#ifdef USE_CUDA + onnxruntime::kCudaExecutionProvider, +#elif USE_ROCM + onnxruntime::kRocmExecutionProvider, +#endif + }; + + const std::vector output_names = {"final_output"}; + + for (auto& provider_type : all_provider_types) { + std::vector expected_ort_values; + RunModelWithData(model_uri, std::string("RawGraphRun"), provider_type, + input_container, output_names, expected_ort_values); + + std::vector actual_ort_values; + RunModelWithData(ToPathString(new_model_uri), std::string("OptimizedGraphRun"), + provider_type, input_container, output_names, actual_ort_values); + + ASSERT_TRUE(expected_ort_values.size() == actual_ort_values.size()); + constexpr double per_sample_tolerance = 1e-4; + constexpr double relative_per_sample_tolerance = 1e-4; + for (size_t i = 0; i < expected_ort_values.size(); i++) { + auto ret = CompareOrtValue(actual_ort_values[i], expected_ort_values[i], + per_sample_tolerance, relative_per_sample_tolerance, false); + EXPECT_EQ(ret.first, COMPARE_RESULT::SUCCESS) << ret.second; + } + } +} + +TEST(ComputeOptimizerTests, GatherMatMul_ScalarSlicingOnLastDim) { + const logging::Logger* logger = &logging::LoggingManager::DefaultLogger(); + auto model_uri = MODEL_FOLDER "computation_reduction/gather/gather_matmul_scalar_last_dim.onnx"; + std::shared_ptr model; + ASSERT_STATUS_OK(Model::Load(model_uri, model, nullptr, *logger)); + Graph& graph = model->MainGraph(); + std::map op_to_count = CountOpsInGraph(graph); + + onnxruntime::GraphTransformerManager graph_transformation_mgr{1}; + ASSERT_STATUS_OK(graph_transformation_mgr.Register(std::make_unique(), TransformerLevel::Level1)); + ASSERT_STATUS_OK(graph_transformation_mgr.ApplyTransformers(graph, TransformerLevel::Level1, *logger)); + + GraphViewer graph_viewer(graph); + // Check the first branch. + { + const std::vector& consumers = graph.GetConsumerNodes("input1"); + ASSERT_EQ(consumers.size(), 1U); + const Node* gather_node = consumers[0]; + ASSERT_EQ(gather_node->OpType(), "MatMul"); + } + + // Check the second Gather. + { + const std::vector& consumers = graph.GetConsumerNodes("input2"); + ASSERT_EQ(consumers.size(), 1U); + const Node* gather_node = consumers[0]; + ASSERT_EQ(gather_node->OpType(), "Gather"); + + auto& attrs = gather_node->GetAttributes(); + ASSERT_TRUE(attrs.find("axis") != attrs.end()); + + auto& axis_attr = attrs.at("axis"); + auto axis_value = (int)axis_attr.i(); + ASSERT_EQ(axis_value, 2); + } + + // Check MatMul's input and output. + { + const Node* m5 = graph.GetProducerNode("m1_out"); + ASSERT_FALSE(m5 == nullptr); + EXPECT_EQ(m5->OpType(), "MatMul"); + EXPECT_EQ(m5->Name(), "m1"); + + const Node* lhs_input = graph.GetProducerNode(m5->InputDefs()[0]->Name()); + const Node* rhs_input = graph.GetProducerNode(m5->InputDefs()[1]->Name()); + + ASSERT_TRUE(lhs_input == nullptr); + + ASSERT_FALSE(rhs_input == nullptr); + EXPECT_EQ(rhs_input->OpType(), "Unsqueeze"); + } + + // Check result diff after the re-order + onnxruntime::test::TemporaryDirectory tmp_dir{ORT_TSTR("compute_optimizer_test_tmp_dir")}; + PathString new_model_uri{ConcatPathComponent(tmp_dir.Path(), + ORT_TSTR("gather_matmul_scalar_last_dim_optimized.onnx"))}; + ASSERT_STATUS_OK(Model::Save(*model, new_model_uri)); + + int64_t batch_size = 8; + int64_t sequence_length = 16; + int64_t hidden_size = 1024; + + InputContainer input_container; + + input_container.AddInput("input1", {batch_size, sequence_length, hidden_size}, RandomFillFloatVector); + input_container.AddInput("input2", {batch_size, hidden_size, sequence_length}, RandomFillFloatVector); + + static const std::string all_provider_types[] = { + onnxruntime::kCpuExecutionProvider, +#ifdef USE_CUDA + onnxruntime::kCudaExecutionProvider, +#elif USE_ROCM + onnxruntime::kRocmExecutionProvider, +#endif + }; + + const std::vector output_names = {"final_output"}; + + for (auto& provider_type : all_provider_types) { + std::vector expected_ort_values; + RunModelWithData(model_uri, std::string("RawGraphRun"), provider_type, + input_container, output_names, expected_ort_values); + + std::vector actual_ort_values; + RunModelWithData(ToPathString(new_model_uri), std::string("OptimizedGraphRun"), + provider_type, input_container, output_names, actual_ort_values); + + ASSERT_TRUE(expected_ort_values.size() == actual_ort_values.size()); + constexpr double per_sample_tolerance = 1e-4; + constexpr double relative_per_sample_tolerance = 1e-4; + for (size_t i = 0; i < expected_ort_values.size(); i++) { + auto ret = CompareOrtValue(actual_ort_values[i], expected_ort_values[i], + per_sample_tolerance, relative_per_sample_tolerance, false); + EXPECT_EQ(ret.first, COMPARE_RESULT::SUCCESS) << ret.second; + } + } +} + +TEST(ComputeOptimizerTests, GatherMatMul_SlicingOnLastDim) { + const logging::Logger* logger = &logging::LoggingManager::DefaultLogger(); + auto model_uri = MODEL_FOLDER "computation_reduction/gather/gather_matmul_last_dim.onnx"; + std::shared_ptr model; + ASSERT_STATUS_OK(Model::Load(model_uri, model, nullptr, *logger)); + Graph& graph = model->MainGraph(); + std::map op_to_count = CountOpsInGraph(graph); + + onnxruntime::GraphTransformerManager graph_transformation_mgr{1}; + ASSERT_STATUS_OK(graph_transformation_mgr.Register(std::make_unique(), TransformerLevel::Level1)); + ASSERT_STATUS_OK(graph_transformation_mgr.ApplyTransformers(graph, TransformerLevel::Level1, *logger)); + + GraphViewer graph_viewer(graph); + // Check the first branch. + { + const std::vector& consumers = graph.GetConsumerNodes("input1"); + ASSERT_EQ(consumers.size(), 1U); + const Node* gather_node = consumers[0]; + ASSERT_EQ(gather_node->OpType(), "MatMul"); + } + + // Check the second Gather. + { + const std::vector& consumers = graph.GetConsumerNodes("input2"); + ASSERT_EQ(consumers.size(), 1U); + const Node* gather_node = consumers[0]; + ASSERT_EQ(gather_node->OpType(), "Gather"); + + auto& attrs = gather_node->GetAttributes(); + ASSERT_TRUE(attrs.find("axis") != attrs.end()); + + auto& axis_attr = attrs.at("axis"); + auto axis_value = (int)axis_attr.i(); + ASSERT_EQ(axis_value, 2); + } + + // Check MatMul's input and output. + { + const Node* m5 = graph.GetProducerNode("m1_out"); + ASSERT_FALSE(m5 == nullptr); + EXPECT_EQ(m5->OpType(), "MatMul"); + EXPECT_EQ(m5->Name(), "m1"); + + const Node* lhs_input = graph.GetProducerNode(m5->InputDefs()[0]->Name()); + const Node* rhs_input = graph.GetProducerNode(m5->InputDefs()[1]->Name()); + + ASSERT_TRUE(lhs_input == nullptr); + + ASSERT_FALSE(rhs_input == nullptr); + EXPECT_EQ(rhs_input->OpType(), "Gather"); + } + + // Check result diff after the re-order + onnxruntime::test::TemporaryDirectory tmp_dir{ORT_TSTR("compute_optimizer_test_tmp_dir")}; + PathString new_model_uri{ConcatPathComponent(tmp_dir.Path(), + ORT_TSTR("gather_matmul_last_dim_optimized.onnx"))}; + ASSERT_STATUS_OK(Model::Save(*model, new_model_uri)); + + int64_t batch_size = 8; + int64_t sequence_length = 16; + int64_t hidden_size = 1024; + + InputContainer input_container; + + input_container.AddInput("input1", {batch_size, sequence_length, hidden_size}, RandomFillFloatVector); + input_container.AddInput("input2", {batch_size, hidden_size, sequence_length}, RandomFillFloatVector); + + static const std::string all_provider_types[] = { + onnxruntime::kCpuExecutionProvider, +#ifdef USE_CUDA + onnxruntime::kCudaExecutionProvider, +#elif USE_ROCM + onnxruntime::kRocmExecutionProvider, +#endif + }; + + const std::vector output_names = {"final_output"}; + + for (auto& provider_type : all_provider_types) { + std::vector expected_ort_values; + RunModelWithData(model_uri, std::string("RawGraphRun"), provider_type, + input_container, output_names, expected_ort_values); + + std::vector actual_ort_values; + RunModelWithData(ToPathString(new_model_uri), std::string("OptimizedGraphRun"), + provider_type, input_container, output_names, actual_ort_values); + + ASSERT_TRUE(expected_ort_values.size() == actual_ort_values.size()); + constexpr double per_sample_tolerance = 1e-4; + constexpr double relative_per_sample_tolerance = 1e-4; + for (size_t i = 0; i < expected_ort_values.size(); i++) { + auto ret = CompareOrtValue(actual_ort_values[i], expected_ort_values[i], + per_sample_tolerance, relative_per_sample_tolerance, false); + EXPECT_EQ(ret.first, COMPARE_RESULT::SUCCESS) << ret.second; + } + } +} + +TEST(ComputeOptimizerTests, GatherMatMul_ScalarSlicingOnSecondLastDim) { + const logging::Logger* logger = &logging::LoggingManager::DefaultLogger(); + auto model_uri = MODEL_FOLDER "computation_reduction/gather/gather_matmul_scalar_second_last_dim.onnx"; + std::shared_ptr model; + ASSERT_STATUS_OK(Model::Load(model_uri, model, nullptr, *logger)); + Graph& graph = model->MainGraph(); + std::map op_to_count = CountOpsInGraph(graph); + + onnxruntime::GraphTransformerManager graph_transformation_mgr{1}; + ASSERT_STATUS_OK(graph_transformation_mgr.Register(std::make_unique(), TransformerLevel::Level1)); + ASSERT_STATUS_OK(graph_transformation_mgr.ApplyTransformers(graph, TransformerLevel::Level1, *logger)); + + GraphViewer graph_viewer(graph); + // Check the first Gather. + { + const std::vector& consumers = graph.GetConsumerNodes("input1"); + ASSERT_EQ(consumers.size(), 1U); + const Node* gather_node = consumers[0]; + ASSERT_EQ(gather_node->OpType(), "Gather"); + + auto& attrs = gather_node->GetAttributes(); + ASSERT_TRUE(attrs.find("axis") != attrs.end()); + + auto& axis_attr = attrs.at("axis"); + auto axis_value = (int)axis_attr.i(); + ASSERT_EQ(axis_value, 1); + } + + // Check the second branch. + { + const std::vector& consumers = graph.GetConsumerNodes("input2"); + ASSERT_EQ(consumers.size(), 1U); + const Node* gather_node = consumers[0]; + ASSERT_EQ(gather_node->OpType(), "MatMul"); + } + + // Check MatMul(who gathers on the second last dim)'s input and output. + { + const Node* m5 = graph.GetProducerNode("m1_out"); + ASSERT_FALSE(m5 == nullptr); + EXPECT_EQ(m5->OpType(), "MatMul"); + EXPECT_EQ(m5->Name(), "m1"); + + const Node* lhs_input = graph.GetProducerNode(m5->InputDefs()[0]->Name()); + const Node* rhs_input = graph.GetProducerNode(m5->InputDefs()[1]->Name()); + + ASSERT_FALSE(lhs_input == nullptr); + EXPECT_EQ(lhs_input->OpType(), "Unsqueeze"); + + ASSERT_TRUE(rhs_input == nullptr); + } + + // Check result diff after the re-order + onnxruntime::test::TemporaryDirectory tmp_dir{ORT_TSTR("compute_optimizer_test_tmp_dir")}; + PathString new_model_uri{ConcatPathComponent( + tmp_dir.Path(), + ORT_TSTR("gather_matmul_scalar_second_last_dim_optimized.onnx"))}; + ASSERT_STATUS_OK(Model::Save(*model, new_model_uri)); + + int64_t batch_size = 8; + int64_t sequence_length = 16; + int64_t hidden_size = 1024; + + InputContainer input_container; + + input_container.AddInput("input1", {batch_size, sequence_length, hidden_size}, RandomFillFloatVector); + input_container.AddInput("input2", {batch_size, hidden_size, sequence_length}, RandomFillFloatVector); + + static const std::string all_provider_types[] = { + onnxruntime::kCpuExecutionProvider, +#ifdef USE_CUDA + onnxruntime::kCudaExecutionProvider, +#elif USE_ROCM + onnxruntime::kRocmExecutionProvider, +#endif + }; + + const std::vector output_names = {"final_output"}; + + for (auto& provider_type : all_provider_types) { + std::vector expected_ort_values; + RunModelWithData(model_uri, std::string("RawGraphRun"), provider_type, + input_container, output_names, expected_ort_values); + + std::vector actual_ort_values; + RunModelWithData(ToPathString(new_model_uri), std::string("OptimizedGraphRun"), + provider_type, input_container, output_names, actual_ort_values); + + ASSERT_TRUE(expected_ort_values.size() == actual_ort_values.size()); + constexpr double per_sample_tolerance = 1e-4; + constexpr double relative_per_sample_tolerance = 1e-4; + for (size_t i = 0; i < expected_ort_values.size(); i++) { + auto ret = CompareOrtValue(actual_ort_values[i], expected_ort_values[i], + per_sample_tolerance, relative_per_sample_tolerance, false); + EXPECT_EQ(ret.first, COMPARE_RESULT::SUCCESS) << ret.second; + } + } +} + +TEST(ComputeOptimizerTests, GatherMatMul_SlicingOnSecondLastDim) { + const logging::Logger* logger = &logging::LoggingManager::DefaultLogger(); + auto model_uri = MODEL_FOLDER "computation_reduction/gather/gather_matmul_second_last_dim.onnx"; + std::shared_ptr model; + ASSERT_STATUS_OK(Model::Load(model_uri, model, nullptr, *logger)); + Graph& graph = model->MainGraph(); + std::map op_to_count = CountOpsInGraph(graph); + + onnxruntime::GraphTransformerManager graph_transformation_mgr{1}; + ASSERT_STATUS_OK(graph_transformation_mgr.Register(std::make_unique(), TransformerLevel::Level1)); + ASSERT_STATUS_OK(graph_transformation_mgr.ApplyTransformers(graph, TransformerLevel::Level1, *logger)); + + GraphViewer graph_viewer(graph); + // Check the first Gather. + { + const std::vector& consumers = graph.GetConsumerNodes("input1"); + ASSERT_EQ(consumers.size(), 1U); + const Node* gather_node = consumers[0]; + ASSERT_EQ(gather_node->OpType(), "Gather"); + + auto& attrs = gather_node->GetAttributes(); + ASSERT_TRUE(attrs.find("axis") != attrs.end()); + + auto& axis_attr = attrs.at("axis"); + auto axis_value = (int)axis_attr.i(); + ASSERT_EQ(axis_value, 1); + } + + // Check the second branch. + { + const std::vector& consumers = graph.GetConsumerNodes("input2"); + ASSERT_EQ(consumers.size(), 1U); + const Node* gather_node = consumers[0]; + ASSERT_EQ(gather_node->OpType(), "MatMul"); + } + + // Check MatMul's input and output. + { + const Node* m5 = graph.GetProducerNode("m1_out"); + ASSERT_FALSE(m5 == nullptr); + EXPECT_EQ(m5->OpType(), "MatMul"); + EXPECT_EQ(m5->Name(), "m1"); + + const Node* lhs_input = graph.GetProducerNode(m5->InputDefs()[0]->Name()); + const Node* rhs_input = graph.GetProducerNode(m5->InputDefs()[1]->Name()); + + ASSERT_FALSE(lhs_input == nullptr); + EXPECT_EQ(lhs_input->OpType(), "Gather"); + + ASSERT_TRUE(rhs_input == nullptr); + } + + // Check result diff after the re-order + onnxruntime::test::TemporaryDirectory tmp_dir{ORT_TSTR("compute_optimizer_test_tmp_dir")}; + PathString new_model_uri{ConcatPathComponent(tmp_dir.Path(), + ORT_TSTR("gather_matmul_second_last_dim_optimized.onnx"))}; + ASSERT_STATUS_OK(Model::Save(*model, new_model_uri)); + + int64_t batch_size = 8; + int64_t sequence_length = 16; + int64_t hidden_size = 1024; + + InputContainer input_container; + + input_container.AddInput("input1", {batch_size, sequence_length, hidden_size}, RandomFillFloatVector); + input_container.AddInput("input2", {batch_size, hidden_size, sequence_length}, RandomFillFloatVector); + + static const std::string all_provider_types[] = { + onnxruntime::kCpuExecutionProvider, +#ifdef USE_CUDA + onnxruntime::kCudaExecutionProvider, +#elif USE_ROCM + onnxruntime::kRocmExecutionProvider, +#endif + }; + + const std::vector output_names = {"final_output"}; + + for (auto& provider_type : all_provider_types) { + std::vector expected_ort_values; + RunModelWithData(model_uri, std::string("RawGraphRun"), provider_type, + input_container, output_names, expected_ort_values); + + std::vector actual_ort_values; + RunModelWithData(ToPathString(new_model_uri), std::string("OptimizedGraphRun"), + provider_type, input_container, output_names, actual_ort_values); + + ASSERT_TRUE(expected_ort_values.size() == actual_ort_values.size()); + constexpr double per_sample_tolerance = 1e-4; + constexpr double relative_per_sample_tolerance = 1e-4; + for (size_t i = 0; i < expected_ort_values.size(); i++) { + auto ret = CompareOrtValue(actual_ort_values[i], expected_ort_values[i], + per_sample_tolerance, relative_per_sample_tolerance, false); + EXPECT_EQ(ret.first, COMPARE_RESULT::SUCCESS) << ret.second; + } + } +} + +TEST(ComputeOptimizerTests, GatherReshape_ScalarSlicingOnBatchDim) { + const logging::Logger* logger = &logging::LoggingManager::DefaultLogger(); + auto model_uri = MODEL_FOLDER "computation_reduction/gather/gather_reshape_scalar_batch_dim.onnx"; + std::shared_ptr model; + ASSERT_STATUS_OK(Model::Load(model_uri, model, nullptr, *logger)); + Graph& graph = model->MainGraph(); + std::map op_to_count = CountOpsInGraph(graph); + + onnxruntime::GraphTransformerManager graph_transformation_mgr{1}; + ASSERT_STATUS_OK(graph_transformation_mgr.Register(std::make_unique(), TransformerLevel::Level1)); + ASSERT_STATUS_OK(graph_transformation_mgr.ApplyTransformers(graph, TransformerLevel::Level1, *logger)); + + GraphViewer graph_viewer(graph); + // Check the first Gather. + { + const std::vector& consumers = graph.GetConsumerNodes("input1"); + ASSERT_EQ(consumers.size(), 1U); + const Node* gather_node = consumers[0]; + ASSERT_EQ(gather_node->OpType(), "Gather"); + + auto& attrs = gather_node->GetAttributes(); + ASSERT_TRUE(attrs.find("axis") != attrs.end()); + + auto& axis_attr = attrs.at("axis"); + auto axis_value = (int)axis_attr.i(); + ASSERT_EQ(axis_value, 0); + } + + { + const Node* m5 = graph.GetProducerNode("reshape_out"); + ASSERT_FALSE(m5 == nullptr); + EXPECT_EQ(m5->OpType(), "Reshape"); + + const Node* lhs_input = graph.GetProducerNode(m5->InputDefs()[0]->Name()); + const Node* rhs_input = graph.GetProducerNode(m5->InputDefs()[1]->Name()); + + ASSERT_FALSE(lhs_input == nullptr); + EXPECT_EQ(lhs_input->OpType(), "Gather"); + + ASSERT_TRUE(rhs_input == nullptr); + InlinedVector new_shape_const_values; + optimizer_utils::AppendTensorFromInitializer(graph, *m5->InputDefs()[1], new_shape_const_values, true); + ASSERT_EQ(new_shape_const_values.size(), 3U); + ASSERT_EQ(new_shape_const_values[0], 0); + ASSERT_EQ(new_shape_const_values[1], 16); + ASSERT_EQ(new_shape_const_values[2], 64); + } + + // Check result diff after the re-order + onnxruntime::test::TemporaryDirectory tmp_dir{ORT_TSTR("compute_optimizer_test_tmp_dir")}; + PathString new_model_uri{ConcatPathComponent(tmp_dir.Path(), + ORT_TSTR("gather_reshape_scalar_batch_dim_optimized.onnx"))}; + ASSERT_STATUS_OK(Model::Save(*model, new_model_uri)); + + int64_t batch_size = 8; + int64_t sequence_length = 16; + int64_t hidden_size = 1024; + + InputContainer input_container; + + input_container.AddInput("input1", {batch_size, sequence_length, hidden_size}, RandomFillFloatVector); + + static const std::string all_provider_types[] = { + onnxruntime::kCpuExecutionProvider, +#ifdef USE_CUDA + onnxruntime::kCudaExecutionProvider, +#elif USE_ROCM + onnxruntime::kRocmExecutionProvider, +#endif + }; + + const std::vector output_names = {"final_output"}; + + for (auto& provider_type : all_provider_types) { + std::vector expected_ort_values; + RunModelWithData(model_uri, std::string("RawGraphRun"), provider_type, + input_container, output_names, expected_ort_values); + + std::vector actual_ort_values; + RunModelWithData(ToPathString(new_model_uri), std::string("OptimizedGraphRun"), + provider_type, input_container, output_names, actual_ort_values); + + ASSERT_TRUE(expected_ort_values.size() == actual_ort_values.size()); + constexpr double per_sample_tolerance = 1e-4; + constexpr double relative_per_sample_tolerance = 1e-4; + for (size_t i = 0; i < expected_ort_values.size(); i++) { + auto ret = CompareOrtValue(actual_ort_values[i], expected_ort_values[i], + per_sample_tolerance, relative_per_sample_tolerance, false); + EXPECT_EQ(ret.first, COMPARE_RESULT::SUCCESS) << ret.second; + } + } +} + +TEST(ComputeOptimizerTests, GatherReshape_SlicingOnBatchDim) { + const logging::Logger* logger = &logging::LoggingManager::DefaultLogger(); + auto model_uri = MODEL_FOLDER "computation_reduction/gather/gather_reshape_batch_dim.onnx"; + std::shared_ptr model; + ASSERT_STATUS_OK(Model::Load(model_uri, model, nullptr, *logger)); + Graph& graph = model->MainGraph(); + std::map op_to_count = CountOpsInGraph(graph); + + onnxruntime::GraphTransformerManager graph_transformation_mgr{1}; + ASSERT_STATUS_OK(graph_transformation_mgr.Register(std::make_unique(), TransformerLevel::Level1)); + ASSERT_STATUS_OK(graph_transformation_mgr.ApplyTransformers(graph, TransformerLevel::Level1, *logger)); + + GraphViewer graph_viewer(graph); + // Check the first Gather. + { + const std::vector& consumers = graph.GetConsumerNodes("input1"); + ASSERT_EQ(consumers.size(), 1U); + const Node* gather_node = consumers[0]; + ASSERT_EQ(gather_node->OpType(), "Gather"); + + auto& attrs = gather_node->GetAttributes(); + ASSERT_TRUE(attrs.find("axis") != attrs.end()); + + auto& axis_attr = attrs.at("axis"); + auto axis_value = (int)axis_attr.i(); + ASSERT_EQ(axis_value, 0); + } + + { + const Node* m5 = graph.GetProducerNode("reshape_out"); + ASSERT_FALSE(m5 == nullptr); + EXPECT_EQ(m5->OpType(), "Reshape"); + + const Node* lhs_input = graph.GetProducerNode(m5->InputDefs()[0]->Name()); + const Node* rhs_input = graph.GetProducerNode(m5->InputDefs()[1]->Name()); + + ASSERT_FALSE(lhs_input == nullptr); + EXPECT_EQ(lhs_input->OpType(), "Gather"); + + ASSERT_TRUE(rhs_input == nullptr); + InlinedVector new_shape_const_values; + optimizer_utils::AppendTensorFromInitializer(graph, *m5->InputDefs()[1], new_shape_const_values, true); + ASSERT_EQ(new_shape_const_values.size(), 4U); + ASSERT_EQ(new_shape_const_values[0], 0); + ASSERT_EQ(new_shape_const_values[1], 0); + ASSERT_EQ(new_shape_const_values[2], 16); + ASSERT_EQ(new_shape_const_values[3], 64); + } + + // Check result diff after the re-order + onnxruntime::test::TemporaryDirectory tmp_dir{ORT_TSTR("compute_optimizer_test_tmp_dir")}; + PathString new_model_uri{ConcatPathComponent(tmp_dir.Path(), + ORT_TSTR("gather_reshape_batch_dim_optimized.onnx"))}; + ASSERT_STATUS_OK(Model::Save(*model, new_model_uri)); + + int64_t batch_size = 8; + int64_t sequence_length = 16; + int64_t hidden_size = 1024; + + InputContainer input_container; + + input_container.AddInput("input1", {batch_size, sequence_length, hidden_size}, RandomFillFloatVector); + + static const std::string all_provider_types[] = { + onnxruntime::kCpuExecutionProvider, +#ifdef USE_CUDA + onnxruntime::kCudaExecutionProvider, +#elif USE_ROCM + onnxruntime::kRocmExecutionProvider, +#endif + }; + + const std::vector output_names = {"final_output"}; + + for (auto& provider_type : all_provider_types) { + std::vector expected_ort_values; + RunModelWithData(model_uri, std::string("RawGraphRun"), provider_type, + input_container, output_names, expected_ort_values); + + std::vector actual_ort_values; + RunModelWithData(ToPathString(new_model_uri), std::string("OptimizedGraphRun"), + provider_type, input_container, output_names, actual_ort_values); + + ASSERT_TRUE(expected_ort_values.size() == actual_ort_values.size()); + constexpr double per_sample_tolerance = 1e-4; + constexpr double relative_per_sample_tolerance = 1e-4; + for (size_t i = 0; i < expected_ort_values.size(); i++) { + auto ret = CompareOrtValue(actual_ort_values[i], expected_ort_values[i], + per_sample_tolerance, relative_per_sample_tolerance, false); + EXPECT_EQ(ret.first, COMPARE_RESULT::SUCCESS) << ret.second; + } + } +} + +TEST(ComputeOptimizerTests, GatherReshape_ScalarSlicingOnSeqlenDim) { + const logging::Logger* logger = &logging::LoggingManager::DefaultLogger(); + auto model_uri = MODEL_FOLDER "computation_reduction/gather/gather_reshape_scalar_seqlen_dim.onnx"; + std::shared_ptr model; + ASSERT_STATUS_OK(Model::Load(model_uri, model, nullptr, *logger)); + Graph& graph = model->MainGraph(); + std::map op_to_count = CountOpsInGraph(graph); + + onnxruntime::GraphTransformerManager graph_transformation_mgr{1}; + ASSERT_STATUS_OK(graph_transformation_mgr.Register(std::make_unique(), TransformerLevel::Level1)); + ASSERT_STATUS_OK(graph_transformation_mgr.ApplyTransformers(graph, TransformerLevel::Level1, *logger)); + + GraphViewer graph_viewer(graph); + // Check the first Gather. + { + const std::vector& consumers = graph.GetConsumerNodes("input1"); + ASSERT_EQ(consumers.size(), 1U); + const Node* gather_node = consumers[0]; + ASSERT_EQ(gather_node->OpType(), "Gather"); + + auto& attrs = gather_node->GetAttributes(); + ASSERT_TRUE(attrs.find("axis") != attrs.end()); + + auto& axis_attr = attrs.at("axis"); + auto axis_value = (int)axis_attr.i(); + ASSERT_EQ(axis_value, 1); + } + + { + const Node* m5 = graph.GetProducerNode("reshape_out"); + ASSERT_FALSE(m5 == nullptr); + EXPECT_EQ(m5->OpType(), "Reshape"); + + const Node* lhs_input = graph.GetProducerNode(m5->InputDefs()[0]->Name()); + const Node* rhs_input = graph.GetProducerNode(m5->InputDefs()[1]->Name()); + + ASSERT_FALSE(lhs_input == nullptr); + EXPECT_EQ(lhs_input->OpType(), "Gather"); + + ASSERT_TRUE(rhs_input == nullptr); + InlinedVector new_shape_const_values; + optimizer_utils::AppendTensorFromInitializer(graph, *m5->InputDefs()[1], new_shape_const_values, true); + ASSERT_EQ(new_shape_const_values.size(), 3U); + ASSERT_EQ(new_shape_const_values[0], 0); + ASSERT_EQ(new_shape_const_values[1], 16); + ASSERT_EQ(new_shape_const_values[2], 64); + } + + // Check result diff after the re-order + onnxruntime::test::TemporaryDirectory tmp_dir{ORT_TSTR("compute_optimizer_test_tmp_dir")}; + PathString new_model_uri{ConcatPathComponent(tmp_dir.Path(), + ORT_TSTR("gather_reshape_scalar_seqlen_dim_optimized.onnx"))}; + ASSERT_STATUS_OK(Model::Save(*model, new_model_uri)); + + int64_t batch_size = 8; + int64_t sequence_length = 16; + int64_t hidden_size = 1024; + + InputContainer input_container; + + input_container.AddInput("input1", {batch_size, sequence_length, hidden_size}, RandomFillFloatVector); + + static const std::string all_provider_types[] = { + onnxruntime::kCpuExecutionProvider, +#ifdef USE_CUDA + onnxruntime::kCudaExecutionProvider, +#elif USE_ROCM + onnxruntime::kRocmExecutionProvider, +#endif + }; + + const std::vector output_names = {"final_output"}; + + for (auto& provider_type : all_provider_types) { + std::vector expected_ort_values; + RunModelWithData(model_uri, std::string("RawGraphRun"), provider_type, + input_container, output_names, expected_ort_values); + + std::vector actual_ort_values; + RunModelWithData(ToPathString(new_model_uri), std::string("OptimizedGraphRun"), + provider_type, input_container, output_names, actual_ort_values); + + ASSERT_TRUE(expected_ort_values.size() == actual_ort_values.size()); + constexpr double per_sample_tolerance = 1e-4; + constexpr double relative_per_sample_tolerance = 1e-4; + for (size_t i = 0; i < expected_ort_values.size(); i++) { + auto ret = CompareOrtValue(actual_ort_values[i], expected_ort_values[i], + per_sample_tolerance, relative_per_sample_tolerance, false); + EXPECT_EQ(ret.first, COMPARE_RESULT::SUCCESS) << ret.second; + } + } +} + +TEST(ComputeOptimizerTests, GatherReshape_SlicingOnSeqlenDim) { + const logging::Logger* logger = &logging::LoggingManager::DefaultLogger(); + auto model_uri = MODEL_FOLDER "computation_reduction/gather/gather_reshape_seqlen_dim.onnx"; + std::shared_ptr model; + ASSERT_STATUS_OK(Model::Load(model_uri, model, nullptr, *logger)); + Graph& graph = model->MainGraph(); + std::map op_to_count = CountOpsInGraph(graph); + + onnxruntime::GraphTransformerManager graph_transformation_mgr{1}; + ASSERT_STATUS_OK(graph_transformation_mgr.Register(std::make_unique(), TransformerLevel::Level1)); + ASSERT_STATUS_OK(graph_transformation_mgr.ApplyTransformers(graph, TransformerLevel::Level1, *logger)); + + GraphViewer graph_viewer(graph); + // Check the first Gather. + { + const std::vector& consumers = graph.GetConsumerNodes("input1"); + ASSERT_EQ(consumers.size(), 1U); + const Node* gather_node = consumers[0]; + ASSERT_EQ(gather_node->OpType(), "Gather"); + + auto& attrs = gather_node->GetAttributes(); + ASSERT_TRUE(attrs.find("axis") != attrs.end()); + + auto& axis_attr = attrs.at("axis"); + auto axis_value = (int)axis_attr.i(); + ASSERT_EQ(axis_value, 1); + } + + { + const Node* m5 = graph.GetProducerNode("reshape_out"); + ASSERT_FALSE(m5 == nullptr); + EXPECT_EQ(m5->OpType(), "Reshape"); + + const Node* lhs_input = graph.GetProducerNode(m5->InputDefs()[0]->Name()); + const Node* rhs_input = graph.GetProducerNode(m5->InputDefs()[1]->Name()); + + ASSERT_FALSE(lhs_input == nullptr); + EXPECT_EQ(lhs_input->OpType(), "Gather"); + + ASSERT_TRUE(rhs_input == nullptr); + InlinedVector new_shape_const_values; + optimizer_utils::AppendTensorFromInitializer(graph, *m5->InputDefs()[1], new_shape_const_values, true); + ASSERT_EQ(new_shape_const_values.size(), 4U); + ASSERT_EQ(new_shape_const_values[0], 0); + ASSERT_EQ(new_shape_const_values[1], 0); + ASSERT_EQ(new_shape_const_values[2], 16); + ASSERT_EQ(new_shape_const_values[3], 64); + } + + // Check result diff after the re-order + onnxruntime::test::TemporaryDirectory tmp_dir{ORT_TSTR("compute_optimizer_test_tmp_dir")}; + PathString new_model_uri{ConcatPathComponent(tmp_dir.Path(), + ORT_TSTR("gather_reshape_seqlen_dim_optimized.onnx"))}; + ASSERT_STATUS_OK(Model::Save(*model, new_model_uri)); + + int64_t batch_size = 8; + int64_t sequence_length = 16; + int64_t hidden_size = 1024; + + InputContainer input_container; + + input_container.AddInput("input1", {batch_size, sequence_length, hidden_size}, RandomFillFloatVector); + + static const std::string all_provider_types[] = { + onnxruntime::kCpuExecutionProvider, +#ifdef USE_CUDA + onnxruntime::kCudaExecutionProvider, +#elif USE_ROCM + onnxruntime::kRocmExecutionProvider, +#endif + }; + + const std::vector output_names = {"final_output"}; + + for (auto& provider_type : all_provider_types) { + std::vector expected_ort_values; + RunModelWithData(model_uri, std::string("RawGraphRun"), provider_type, + input_container, output_names, expected_ort_values); + + std::vector actual_ort_values; + RunModelWithData(ToPathString(new_model_uri), std::string("OptimizedGraphRun"), + provider_type, input_container, output_names, actual_ort_values); + + ASSERT_TRUE(expected_ort_values.size() == actual_ort_values.size()); + constexpr double per_sample_tolerance = 1e-4; + constexpr double relative_per_sample_tolerance = 1e-4; + for (size_t i = 0; i < expected_ort_values.size(); i++) { + auto ret = CompareOrtValue(actual_ort_values[i], expected_ort_values[i], + per_sample_tolerance, relative_per_sample_tolerance, false); + EXPECT_EQ(ret.first, COMPARE_RESULT::SUCCESS) << ret.second; + } + } +} + +TEST(ComputeOptimizerTests, GatherReshape_SlicingOnSeqlenDim2) { + const logging::Logger* logger = &logging::LoggingManager::DefaultLogger(); + auto model_uri = MODEL_FOLDER "computation_reduction/gather/gather_reshape_seqlen_dim2.onnx"; + std::shared_ptr model; + ASSERT_STATUS_OK(Model::Load(model_uri, model, nullptr, *logger)); + Graph& graph = model->MainGraph(); + std::map op_to_count = CountOpsInGraph(graph); + + onnxruntime::GraphTransformerManager graph_transformation_mgr{1}; + ASSERT_STATUS_OK(graph_transformation_mgr.Register(std::make_unique(), TransformerLevel::Level1)); + ASSERT_STATUS_OK(graph_transformation_mgr.ApplyTransformers(graph, TransformerLevel::Level1, *logger)); + + GraphViewer graph_viewer(graph); + // Check the first Gather. + { + const std::vector& consumers = graph.GetConsumerNodes("input1"); + ASSERT_EQ(consumers.size(), 1U); + const Node* gather_node = consumers[0]; + ASSERT_EQ(gather_node->OpType(), "Gather"); + + auto& attrs = gather_node->GetAttributes(); + ASSERT_TRUE(attrs.find("axis") != attrs.end()); + + auto& axis_attr = attrs.at("axis"); + auto axis_value = (int)axis_attr.i(); + ASSERT_EQ(axis_value, 1); + } + + { + const Node* m5 = graph.GetProducerNode("reshape_out"); + ASSERT_FALSE(m5 == nullptr); + EXPECT_EQ(m5->OpType(), "Reshape"); + + const Node* lhs_input = graph.GetProducerNode(m5->InputDefs()[0]->Name()); + const Node* rhs_input = graph.GetProducerNode(m5->InputDefs()[1]->Name()); + + ASSERT_FALSE(lhs_input == nullptr); + EXPECT_EQ(lhs_input->OpType(), "Gather"); + + ASSERT_TRUE(rhs_input == nullptr); + InlinedVector new_shape_const_values; + optimizer_utils::AppendTensorFromInitializer(graph, *m5->InputDefs()[1], new_shape_const_values, true); + ASSERT_EQ(new_shape_const_values.size(), 4U); + ASSERT_EQ(new_shape_const_values[0], 0); + ASSERT_EQ(new_shape_const_values[1], 31); + ASSERT_EQ(new_shape_const_values[2], 16); + ASSERT_EQ(new_shape_const_values[3], 64); + } + + // Check result diff after the re-order + onnxruntime::test::TemporaryDirectory tmp_dir{ORT_TSTR("compute_optimizer_test_tmp_dir")}; + PathString new_model_uri{ConcatPathComponent(tmp_dir.Path(), + ORT_TSTR("gather_reshape_seqlen_dim2_optimized.onnx"))}; + ASSERT_STATUS_OK(Model::Save(*model, new_model_uri)); + + int64_t batch_size = 8; + int64_t sequence_length = 128; + int64_t hidden_size = 1024; + + InputContainer input_container; + + input_container.AddInput("input1", {batch_size, sequence_length, hidden_size}, RandomFillFloatVector); + + static const std::string all_provider_types[] = { + onnxruntime::kCpuExecutionProvider, +#ifdef USE_CUDA + onnxruntime::kCudaExecutionProvider, +#elif USE_ROCM + onnxruntime::kRocmExecutionProvider, +#endif + }; + + const std::vector output_names = {"final_output"}; + + for (auto& provider_type : all_provider_types) { + std::vector expected_ort_values; + RunModelWithData(model_uri, std::string("RawGraphRun"), provider_type, + input_container, output_names, expected_ort_values); + + std::vector actual_ort_values; + RunModelWithData(ToPathString(new_model_uri), std::string("OptimizedGraphRun"), + provider_type, input_container, output_names, actual_ort_values); + + ASSERT_TRUE(expected_ort_values.size() == actual_ort_values.size()); + constexpr double per_sample_tolerance = 1e-4; + constexpr double relative_per_sample_tolerance = 1e-4; + for (size_t i = 0; i < expected_ort_values.size(); i++) { + auto ret = CompareOrtValue(actual_ort_values[i], expected_ort_values[i], + per_sample_tolerance, relative_per_sample_tolerance, false); + EXPECT_EQ(ret.first, COMPARE_RESULT::SUCCESS) << ret.second; + } + } +} + +TEST(ComputeOptimizerTests, GatherRobertaE2E) { + const logging::Logger* logger = &logging::LoggingManager::DefaultLogger(); + // Be noted, all dropout have ratio be 0.0, to make it easier to compare when running with session. + // This did not affect the transformer tests, because we did not remove the Dropout of ratio 0. in the middle. + auto model_uri = MODEL_FOLDER "computation_reduction/gather/gather_roberta_e2e.onnx"; + std::shared_ptr model; + ASSERT_STATUS_OK(Model::Load(model_uri, model, nullptr, *logger)); + Graph& graph = model->MainGraph(); + std::map op_to_count = CountOpsInGraph(graph); + + onnxruntime::GraphTransformerManager graph_transformation_mgr{3}; + ASSERT_STATUS_OK(graph_transformation_mgr.Register(std::make_unique(), TransformerLevel::Level1)); + ASSERT_STATUS_OK(graph_transformation_mgr.Register(std::make_unique(), TransformerLevel::Level1)); + ASSERT_STATUS_OK(graph_transformation_mgr.ApplyTransformers(graph, TransformerLevel::Level1, *logger)); + + GraphViewer graph_viewer(graph); + // Check the first Gather. + { + const std::vector& consumers = graph.GetConsumerNodes("c1_out"); + const Node* gather_node = nullptr; + for (auto p_node : consumers) { + ASSERT_FALSE(p_node == nullptr); + if (p_node->OpType().compare("Gather") == 0) { + gather_node = p_node; + const Node* cast_node = graph.GetProducerNode(gather_node->InputDefs()[0]->Name()); + EXPECT_EQ(cast_node->OpType(), "Cast"); + EXPECT_EQ(cast_node->Name(), "c1"); + const auto& gather_consumers = graph.GetConsumerNodes(gather_node->OutputDefs()[0]->Name()); + EXPECT_EQ(gather_consumers[0]->OpType(), "Unsqueeze"); + break; + } + } + + ASSERT_FALSE(gather_node == nullptr); + } + + // Check the second Gather. + { + const std::vector& consumers = graph.GetConsumerNodes("d1_out"); + const Node* gather_node = nullptr; + for (auto p_node : consumers) { + ASSERT_FALSE(p_node == nullptr); + if (p_node->OpType().compare("Gather") == 0) { + gather_node = p_node; + const Node* dropout_node = graph.GetProducerNode(gather_node->InputDefs()[0]->Name()); + EXPECT_EQ(dropout_node->OpType(), "Dropout"); + EXPECT_EQ(dropout_node->Name(), "d1"); + const auto& gather_consumers = graph.GetConsumerNodes(gather_node->OutputDefs()[0]->Name()); + EXPECT_EQ(gather_consumers[0]->OpType(), "Add"); + EXPECT_EQ(gather_consumers[0]->Name(), "a6"); + break; + } + } + + ASSERT_FALSE(gather_node == nullptr); + } + + // Check the input/output of the original Gather node. + { + const std::vector& consumers = graph.GetConsumerNodes("layernorm2_out"); + ASSERT_TRUE(consumers.size() == 1); + ASSERT_FALSE(consumers[0] == nullptr); + EXPECT_EQ(consumers[0]->OpType(), "Dropout"); + EXPECT_EQ(consumers[0]->Name(), "d6"); + } + + // Check MatMul(who gathers on the second last dim)'s input and output. + { + const Node* m5 = graph.GetProducerNode("m5_out"); + ASSERT_FALSE(m5 == nullptr); + EXPECT_EQ(m5->OpType(), "MatMul"); + EXPECT_EQ(m5->Name(), "m5"); + + const Node* lhs_input = graph.GetProducerNode(m5->InputDefs()[0]->Name()); + const Node* rhs_input = graph.GetProducerNode(m5->InputDefs()[1]->Name()); + + ASSERT_FALSE(lhs_input == nullptr); + EXPECT_EQ(lhs_input->OpType(), "Unsqueeze"); + + ASSERT_FALSE(rhs_input == nullptr); + EXPECT_EQ(rhs_input->OpType(), "Transpose"); + EXPECT_EQ(rhs_input->Name(), "transpose1"); + } + + // Check Add(who has broadcastable dim on gather axis)'s input and output. + { + const Node* a4 = graph.GetProducerNode("a4_out"); + ASSERT_FALSE(a4 == nullptr); + EXPECT_EQ(a4->OpType(), "Add"); + EXPECT_EQ(a4->Name(), "a4"); + + const std::vector& consumers = graph.GetConsumerNodes("a4_out"); + ASSERT_TRUE(consumers.size() == 1); + ASSERT_FALSE(consumers[0] == nullptr); + EXPECT_EQ(consumers[0]->OpType(), "Squeeze"); + } + + // Check result diff after the re-order + onnxruntime::test::TemporaryDirectory tmp_dir{ORT_TSTR("compute_optimizer_test_tmp_dir")}; + PathString new_model_uri{ConcatPathComponent(tmp_dir.Path(), + ORT_TSTR("gather_roberta_e2e_optimized.onnx"))}; + ASSERT_STATUS_OK(Model::Save(*model, new_model_uri)); + + int64_t batch_size = 8; + int64_t sequence_length = 16; + int64_t hidden_size = 1024; + + InputContainer input_container; + + input_container.AddInput("input", {batch_size, sequence_length, hidden_size}, RandomFillFloatVector); + + const TensorShapeVector dims_mask = {batch_size, sequence_length}; + std::vector attention_mask(TensorShape(dims_mask).Size(), 1); + input_container.AddInput("attention_mask", dims_mask, attention_mask); + + input_container.AddInput("matmul1.weight", {hidden_size, 1024}, RandomFillHalfVector); + input_container.AddInput("add1.bias", {1024}, RandomFillHalfVector); + + input_container.AddInput("matmul2.weight", {hidden_size, 1024}, RandomFillHalfVector); + input_container.AddInput("add2.bias", {1024}, RandomFillHalfVector); + + input_container.AddInput("matmul3.weight", {hidden_size, 1024}, RandomFillHalfVector); + input_container.AddInput("add3.bias", {1024}, RandomFillHalfVector); + + input_container.AddInput("matmul4.weight", {hidden_size, 1024}, RandomFillHalfVector); + input_container.AddInput("add4.bias", {1024}, RandomFillHalfVector); + + input_container.AddInput("layer_norm1.weight", {hidden_size}, RandomFillFloatVector); + input_container.AddInput("layer_norm1.bias", {hidden_size}, RandomFillFloatVector); + + input_container.AddInput("matmul7.weight", {hidden_size, hidden_size * 4}, RandomFillHalfVector); + input_container.AddInput("add7.bias", {hidden_size * 4}, RandomFillHalfVector); + + input_container.AddInput("matmul8.weight", {hidden_size * 4, hidden_size}, RandomFillHalfVector); + input_container.AddInput("add8.bias", {hidden_size}, RandomFillHalfVector); + + input_container.AddInput("layer_norm2.weight", {hidden_size}, RandomFillFloatVector); + input_container.AddInput("layer_norm2.bias", {hidden_size}, RandomFillFloatVector); + + static const std::string all_provider_types[] = { + onnxruntime::kCpuExecutionProvider, +#ifdef USE_CUDA + onnxruntime::kCudaExecutionProvider, +#elif USE_ROCM + onnxruntime::kRocmExecutionProvider, +#endif + }; + + const std::vector output_names = {"final_output"}; + + for (auto& provider_type : all_provider_types) { + std::vector expected_ort_values; + RunModelWithData(model_uri, std::string("RawGraphRun"), provider_type, + input_container, output_names, expected_ort_values); + + std::vector actual_ort_values; + RunModelWithData(ToPathString(new_model_uri), std::string("OptimizedGraphRun"), + provider_type, input_container, output_names, actual_ort_values); + + ASSERT_TRUE(expected_ort_values.size() == actual_ort_values.size()); + + // "expected 0.793675 (3f4b2e44), got 0.79232 (3f4ad584), diff: 0.00135422, tol=0.000179367 idx=4276. + // 1713 of 8192 differ" + // Loose the atol a bit because we see the MatMuls results differs once we move Gather before it. + constexpr double per_sample_tolerance = 2e-3; + constexpr double relative_per_sample_tolerance = 2e-3; + for (size_t i = 0; i < expected_ort_values.size(); i++) { + auto ret = CompareOrtValue(actual_ort_values[i], expected_ort_values[i], + per_sample_tolerance, relative_per_sample_tolerance, false); + EXPECT_EQ(ret.first, COMPARE_RESULT::SUCCESS) << ret.second; + } + } +} +#endif + +} // namespace test +} // namespace onnxruntime + +#endif diff --git a/onnxruntime/test/optimizer/graph_transform_test.cc b/onnxruntime/test/optimizer/graph_transform_test.cc index f84058845c..eb0d2c9ebd 100755 --- a/onnxruntime/test/optimizer/graph_transform_test.cc +++ b/onnxruntime/test/optimizer/graph_transform_test.cc @@ -24,7 +24,6 @@ #include "core/optimizer/bias_softmax_fusion.h" #include "core/optimizer/cast_elimination.h" #include "core/optimizer/common_subexpression_elimination.h" -#include "core/optimizer/computation_reduction.h" #include "core/optimizer/concat_slice_elimination.h" #include "core/optimizer/constant_folding.h" #include "core/optimizer/constant_sharing.h" @@ -5069,199 +5068,6 @@ TEST_F(GraphTransformationTests, MatMulIntegerToFloatTest) { #endif -// LayerNormalization implementation is in contrib namespace (OnnxDomain 1), so -// Without contib_ops enabled, we cannot parse the graph correctly. -#ifndef DISABLE_CONTRIB_OPS -// We used Opset 12 for testing to make sure we are not using GatherND OnnxDomain Opset 1. -static void GatherNDComputationReductionTest(const std::string op_type, logging::Logger& logger) { - std::string op_type_lower = op_type; - std::transform(op_type_lower.begin(), op_type_lower.end(), op_type_lower.begin(), [](unsigned char c) { return std::tolower(c); }); - std::string file_path = std::string("testdata/transform/computation_reduction/gathernd_") + op_type_lower + std::string(".onnx"); - std::shared_ptr model; - ASSERT_STATUS_OK(Model::Load(ToPathString(file_path), model, nullptr, logger)); - Graph& graph = model->MainGraph(); - std::map op_to_count = CountOpsInGraph(graph); - - onnxruntime::GraphTransformerManager graph_transformation_mgr{1}; - ASSERT_STATUS_OK(graph_transformation_mgr.Register(std::make_unique(), TransformerLevel::Level1)); - ASSERT_STATUS_OK(graph_transformation_mgr.ApplyTransformers(graph, TransformerLevel::Level1, logger)); - - GraphViewer graph_viewer(graph); - const auto& node_topology_list = graph_viewer.GetNodesInTopologicalOrder(); - - Node* gathernd_node = nullptr; - for (auto node_index : node_topology_list) { - Node* p_node = graph.GetNode(node_index); - ASSERT_FALSE(p_node == nullptr); - if (p_node->OpType().compare("GatherND") == 0) { - gathernd_node = p_node; - EXPECT_EQ(gathernd_node->MutableInputDefs()[0]->Name(), "input"); - const auto& consumers = graph.GetConsumerNodes(gathernd_node->MutableOutputDefs()[0]->Name()); - EXPECT_EQ(consumers[0]->OpType(), op_type); - } - } - - ASSERT_FALSE(gathernd_node == nullptr); -} - -TEST_F(GraphTransformationTests, ComputationReductionTransformer_GatherND_Gelu) { - GatherNDComputationReductionTest("Gelu", *logger_); -} - -TEST_F(GraphTransformationTests, ComputationReductionTransformer_GatherND_Add) { - GatherNDComputationReductionTest("Add", *logger_); -} - -TEST_F(GraphTransformationTests, ComputationReductionTransformer_GatherND_LayerNormalization) { - GatherNDComputationReductionTest("LayerNormalization", *logger_); -} - -TEST_F(GraphTransformationTests, ComputationReductionTransformer_GatherND_MatMul) { - GatherNDComputationReductionTest("MatMul", *logger_); -} - -static void RunGatherNDE2EGraph(std::vector& run_results, const PathString& model_uri, - const std::string session_log_id, const std::string& provider_type, - const std::vector& dims_input, - const std::vector& input_values, - const std::vector& dims_unsqueezed_masked_lm_positions, - const std::vector& values_unsqueezed_masked_lm_positions) { - SessionOptions so; - // we don't want any transformation here. - so.graph_optimization_level = TransformerLevel::Default; - so.session_logid = session_log_id; - - InferenceSession session_object{so, GetEnvironment()}; - std::unique_ptr execution_provider; - if (provider_type == onnxruntime::kCpuExecutionProvider) - execution_provider = DefaultCpuExecutionProvider(); - else if (provider_type == onnxruntime::kCudaExecutionProvider) - execution_provider = DefaultCudaExecutionProvider(); - else if (provider_type == onnxruntime::kRocmExecutionProvider) - execution_provider = DefaultRocmExecutionProvider(); - EXPECT_TRUE(session_object.RegisterExecutionProvider(std::move(execution_provider)).IsOK()); - - Status st; - ASSERT_TRUE((st = session_object.Load(model_uri)).IsOK()) << st; - ASSERT_TRUE((st = session_object.Initialize()).IsOK()) << st; - - OrtValue input1; - CreateMLValue(TestCPUExecutionProvider()->GetAllocator(0, OrtMemTypeDefault), dims_input, input_values, &input1); - OrtValue input2; - CreateMLValue(TestCPUExecutionProvider()->GetAllocator(0, OrtMemTypeDefault), dims_unsqueezed_masked_lm_positions, - values_unsqueezed_masked_lm_positions, &input2); - - NameMLValMap feeds; - feeds.insert(std::make_pair("input", input1)); - feeds.insert(std::make_pair("unsqueezed_masked_lm_positions", input2)); - - // prepare outputs - std::vector output_names; - output_names.push_back("output"); - output_names.push_back("gather_output"); - - // Now run - RunOptions run_options; - st = session_object.Run(run_options, feeds, output_names, &run_results); - - EXPECT_TRUE(st.IsOK()); -} - -TEST_F(GraphTransformationTests, ComputationReductionTransformer_GatherND_E2E) { - constexpr const ORTCHAR_T* model_uri = MODEL_FOLDER "computation_reduction/e2e.onnx"; - std::shared_ptr model; - ASSERT_STATUS_OK(Model::Load(model_uri, model, nullptr, *logger_)); - Graph& graph = model->MainGraph(); - std::map op_to_count = CountOpsInGraph(graph); - - onnxruntime::GraphTransformerManager graph_transformation_mgr{5}; - ASSERT_STATUS_OK(graph_transformation_mgr.Register(std::make_unique(), TransformerLevel::Level1)); - ASSERT_STATUS_OK(graph_transformation_mgr.ApplyTransformers(graph, TransformerLevel::Level1, *logger_)); - - // check the expected node orders. - { - GraphViewer graph_viewer(graph); - const auto& node_topology_list = graph_viewer.GetNodesInTopologicalOrder(); - - Node* gathernd_node = nullptr; - for (auto node_index : node_topology_list) { - Node* p_node = graph.GetNode(node_index); - ASSERT_FALSE(p_node == nullptr); - if (p_node->OpType().compare("GatherND") == 0) { - gathernd_node = p_node; - const Node* layer_norm_node = graph.GetProducerNode(gathernd_node->MutableInputDefs()[0]->Name()); - EXPECT_EQ(layer_norm_node->OpType(), "LayerNormalization"); - EXPECT_EQ(layer_norm_node->Name(), "layer_norm_1"); - const auto& consumers = graph.GetConsumerNodes(gathernd_node->MutableOutputDefs()[0]->Name()); - EXPECT_EQ(consumers[0]->OpType(), "MatMul"); - EXPECT_EQ(consumers[0]->Name(), "matmul_1"); - break; - } - } - - ASSERT_FALSE(gathernd_node == nullptr); - } - - // check result diff after the re-order - auto new_model_uri = "computation_reduction_transformer_after.onnx"; - ASSERT_STATUS_OK(Model::Save(*model, new_model_uri)); - - float scale = 1.f; - float mean = 0.f; - float seed = 123.f; - std::default_random_engine generator_float{gsl::narrow_cast(seed)}; - std::normal_distribution distribution_float{mean, scale}; - - int batch_size = 8; - int sequence = 128; - int hidden_size = 128; - int dynamic_predict_count = 20; - const std::vector dims_input = {batch_size, sequence, hidden_size}; - std::vector input_values(TensorShape(dims_input).Size()); - std::for_each(input_values.begin(), input_values.end(), - [&generator_float, &distribution_float](float& value) { value = distribution_float(generator_float); }); - - const std::vector dims_unsqueezed_masked_lm_positions = {batch_size, dynamic_predict_count, 1}; - std::vector values_unsqueezed_masked_lm_positions(TensorShape(dims_unsqueezed_masked_lm_positions).Size()); - - std::random_device rd; // obtain a random number from hardware - std::mt19937 eng(rd()); // seed the generator - std::uniform_int_distribution<> distr(0, sequence - 1); // define the range - std::for_each(values_unsqueezed_masked_lm_positions.begin(), values_unsqueezed_masked_lm_positions.end(), - [&distr, &eng](int64_t& value) { value = distr(eng); }); - - static const std::string all_provider_types[] = { - onnxruntime::kCpuExecutionProvider, -#ifdef USE_CUDA - onnxruntime::kCudaExecutionProvider, -#elif USE_ROCM - onnxruntime::kRocmExecutionProvider, -#endif - }; - - for (auto& provider_type : all_provider_types) { - std::vector expected_ort_values; - RunGatherNDE2EGraph(expected_ort_values, model_uri, std::string("RawGraphRun"), provider_type, - dims_input, input_values, dims_unsqueezed_masked_lm_positions, - values_unsqueezed_masked_lm_positions); - - std::vector actual_ort_values; - RunGatherNDE2EGraph(actual_ort_values, ToPathString(new_model_uri), std::string("OptimizedGraphRun"), provider_type, - dims_input, input_values, dims_unsqueezed_masked_lm_positions, - values_unsqueezed_masked_lm_positions); - - ASSERT_TRUE(expected_ort_values.size() == actual_ort_values.size()); - constexpr double per_sample_tolerance = 1e-4; - constexpr double relative_per_sample_tolerance = 1e-4; - for (size_t i = 0; i < expected_ort_values.size(); i++) { - auto ret = CompareOrtValue(actual_ort_values[i], expected_ort_values[i], - per_sample_tolerance, relative_per_sample_tolerance, false); - EXPECT_EQ(ret.first, COMPARE_RESULT::SUCCESS) << ret.second; - } - } -} -#endif - #ifndef DISABLE_CONTRIB_OPS template static void TestMatMulScaleFusion( diff --git a/onnxruntime/test/testdata/transform/computation_reduction/e2e.onnx b/onnxruntime/test/testdata/transform/computation_reduction/e2e.onnx deleted file mode 100755 index b3961b84af80ec1fcad451142b832642b3f0b302..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 201861 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%0Ak z(!0KL=;pnhUcH}$QD+_riy?#?&Al-Gc&*r-?1;5R+O)7tjTF``7Fwaq$OtH2Q=z)$+mMw3#AWMg&3g?`L|mND+GLev-0gA;r!&g<5GO zl=f+3xr;M2TPLG!!WWv>qZjYmC!=UWljKXiH1cKoQ;khO@ojK-SY+5zS@8%&Mc9f1 zOU*Ij+i~6>GQTBJmri$$XO1BM4E+~VmfLG`-t~mWY{~SySUdBaNl%7OyDTQTgb6 z-Zlt-8wK=KpG;q5{dj}-LtNBIL680uVdQFq{rp+|cJRG(_OrgEw7n};svRTcO?(%L ztR@$k;pnyV3?+PbLQ)v_!(J7V>~Se5Z@NSe*uq)k6Nm#beX%6j7BN2-P>gn0sI_Qd zV!$B!HC!4$!wgYYt%ptQE38bIL)%RGE^!n@tubc>49uZU=C zYpQK##_FvA;Tq!2pQq`FHoZpfOAPQI?~xt)ZlT$B%syrBYg<%5W-If|$*_rBKaRq? zsv&q_oD82kW5is;{!~)=m!wkDXIGFk6~fPGKJ{_6oa`jq=r7VD|;cr<3Y=g|Jq z>Fk-zi8(EeFp}lxH4KZ=Y;%RzV_Hm)`Xs@NnEn2+$970=k#zXU1 z3q8;&rY`kHm=ye(Qn>4rr7#%JYkH!Zcch&g?$D_ZPlWAu1gcWGhF|QnUwh&o>26#unjBm)fxTC+`T8{ZRZT$FYza#H1k%5b55laM zKUoy)qMG*$$-}`IKAa0Wf9M76PjbMQ^9fM)7>*G)|Im!t^`zaDN=jRpKk|;5`9WqV zG}$c1?I=LyyfWq;RQ>hb3vsfFJW{jc~5$+IjN_N}1T->2frS8E(m z>MK3F+<6SqARf;2`RoNH(%omCM^N=_#67lX)IM?$$ zc`!HenAJkc<(&5|v&(d#-V0K9ts(cgJATGFLD_B?3W843>p73eVYO}B%TKayyxkJyGb9o?e3Woj)fQbS-;YyB>F7LpzraRHRpj_zg`9rkT6Knd z=+^HDedPV>zwe`|du=G~ORsNXKk1liKuSmGjE|%!9-*qmf99?T>FKP6+GAoPm|3 z^1SJZXgsx_7PQEt#eFM%sV@`V%)}B%Lzv0n#jd5_Tj*EnKRQs? z1qMY=#gWAs_-8+dUTk6~Sy*pK={51)rk#d|@jZXIGg|k#(%P_Y;#_zSY)u<2V*2FZ z?~x|@%~>wv4`x(pDurC;wyiuf0yB3m5Eqp?_>LNY$%dAcl)sdw+^nVE-UTRWm!|R7 zHmF~JnI`dflH#TzP#f+inXf&L%(%~IM}4uf%?fW$cw>lP96g!cBsx`k;?q?Jst8CF zE&P0lUUi1L^xr4KzipAE?c7XXxUVyBZY}Se-_bv>-6CY|A<4DquBaQ|7em$R$&T|u zQa*~z%@d6|4!`mpk;bgAysP(UD9xi+Cql4u^jA?Kn~d7oinLQ}1gOB)*-yoqW=~6|KiB8e zLJwscZR3L#vLD2ORU@D?G8n}{dua}z)sr%2z-FToWSaxKKc-qif2a`lJ|Iho`vgRh-YuoNl8X8jfph;i5}kTP9^K)cruMqqnVt8Jd?JT ztPXFa&%84*yCaMKQ;t%}%4k$~`AAR54O7DOVCr>4XfM4+E-!{*bjfJkg%kBJza)+} zOVincl|sHmja+#@AYmWjgL6bv^_8JJBnO7i-4Qf?5e3>Fqn|xAC1=yw(OObSC%UOq z_U#Q41$Jk?Z!D(QAID(x$D1NcwFd?^OvIe6D@fYnAyr3zCyUNZOuT1~yhI(?wA>+` zm}?aME)m+?Yq_tX505%E^xt6s?dk7@<@&F*X?|Bc2j{c5C(!`@4DX(jkBdQrFyvM% znMNqldzDDUF6jx4Im~f*=>eOG%*-(Fi|?}LSbhH-b-0hfnbm5LAAV3g<(}f~xh{0> z{TJ#y%H2r?2U6y~{EK7CDAr_`+Ja~FbLJ4zb^ebQ>Ga0)m73U{t3>`LC%IQ0hj|}| zz$T~4tR&EbzNd9w`s_Ecnm?H#VuEWs5|l=&+A^CuhQ#nPFM}k+x~% zQL*h3VYvQ=n140};~q1snfZ8k1NMvMJ0^&|`{vQG6U@i`w3|wJp0}t~8pSf~2~P+@ zBKsV}ro1DgLrxIq?V%vsEHP@Sp~l9OG+^8gfj{-sVU|NXXU9=;))U&bRUW^lO~NL_ zhy3h5K{tL*ri0N1xOyp{+Ut3zuS4{yhk#e{CP`n;NEUyx#hJ<0nDN0H@e^DzYkeH< zrb{z}As6=x57W6Fqr_$hMe6%+1-@m7y*Bi-vam0UJrmYl=%?>s9Dg@ccrFS>OwAHOHvC@GRKZ@^}kyHjRhM-hIM4`Fk`3@S7wR7Y!TUH(eRb-(V ze2=2eUlb`%oXNH_170cJAW}b(&#^xuq(B+XJNwh3X6`>5?I)=mB?KL5p)%b_jDIqh zYBq5%*3KCLQwLGuj2N`ujz!j^Uidv-8Pn|4DQJuv1-cHv^`*+R!u2Pe`J{=5`w!DB z?h*}oVS&{jeMRQJYDy0>puq<{@oTyho^l@BeDQC(u>G@ed_En`$9=^8)0%j7t~XLX z1!Jq<5Ue$Cra>taFit_5mUC9BN9b)bE**^@JX`dc7KHh4ZcFZL+(KSn!%(-8pHbF^ znB%5Qem|HQo;{0{UfV#6^K^3?-QigjhlP&5$h)vb(rFe13&+c%;<^l(tB)e>16@$# zVNK6U96_@4DLQks=y$v~5?5xyz2gjZWN_x`Y#7wzC*yg(7F4vIVbY^s?5&qjkAzl9 z`Ef%moZ*Tm16Gq)TNiSX&LHQFI`G}AgN@&R(VJ-=2p+XZ(syz$_RovvoOKJ?1)U(5 zN~W`LXZv)H1Tk~c=`Rk8yV(=4(kmWC^-=W6NDh6Bl|m=my% zq~}b5!N})NL|cAH+BL3EnX=}^X`wORiA_tD743~JQLMxD6}w&x7Mm%1dXvhk%Zd1t@3z({P^G!bu3#=@)J8s&d2#o;3} z@Y(YXt!J;$*|CY(x!)7V7EeQf(+Fy@I7;POe$ZP!7byeWP?1na*}UfVjB6HipQ}OP ztPTRl&PB*3p8p-UM@&*MwzjkX`DQTGx&QUiNS+66&!Dzw6R0o?d3j|BqAGd`o&6P* zVSk1hpu1!pXE<-vrHtycKaj0ME}35S$Az*I3ceJLF9!^f8&pk~UPSPD$3c{?b)gOY z0&!rT;FCH%4M>vt^=^Paq2f+`+_v*%_VYB@lpUe?u@Y?4U5;5b zuc=|w6`IA*n9@t0I8^0{N(pBsXb#@gZ=hbv6Unw9hrXqIqbuJGL01)VbYrMk?{I^& zDZauu!5zAsr3-Rpmf(P?*kw6@hV|@^cl%37T4RK@M;0J!-5i_<@T0cW<78Z3LGKPW zQej0d4Vu%3Vlrw(&fm7M-RXm2zigx*pB<&BPb&DveHGG;?pQPBI}HoIEc4{PjI1&{ z@#gYmBxq=oqwOsc$J|I~&2UUy>yA*p$Kn^~A`0hDj_;vf_%flI64`ehlO|y%u1POE_J0EfuQFh}`CB0jKRLIHNZdpA>aqd|)vSN8KUa9!(T^!V?Yy9K`YZ zG%`UK$$kz&x1lcX>D{A}Y0=nxCLHA7L<2R|@#VQWnxDv^5@CS2>^i#F#}_{7W9a5L zTReI$;Cgg1md{bZ`_n0uFr-S>xR;q<)6L;ElK;=2jfS=KwXiP`RIO`B^1Ti~A+MQg zdGv3*%!PH4nv5*EKArO;JO8B3{eAG4_9yZB@dy-f|7MUWXW`=KL)PyHO!gd)Nr?k6 z+9sOxovnn?(`iUBuqEBWZir&PuAMOXs4N>U1Ia0)01tNM^ z5NnFF@kfw7<-CzW(No~6#2Otrh8R2fck=!+5sDfE=?Qm3Op0bEM^_z%8RmamNn6ck8W7*S3)}-%gCkgBRaZz0lsOT5byFs zF~NTl_Bp(x2Cq(1Fq%mBR$Jp&kx#9+{V3>EJw1Hf4>fM>}R+yC?nQ_y>(&Iuq~01MwkPO_a0V zxye-v2X@-&u*I{I>W0CO@vP~#X6_?tbU`p!VaPxB$8MbTKa zG!o@&&d|1L%tY{xMBPAJr1C7$h-V!+%Ze%5qL%d1f1%M=Bk^0I72dw8B=s}%#4E#o z$f+Mdrj65>%VUMymgA&l(I!ssABY(y)nc^77@swBNq@*Gy3dRsQ?0*fZA25<&55P- zMAl&b*-f3FhNG#4y(p{i$c9#!3;7#WG2iSo4RqGQm?UfDq>aRk(B0&{MJ{WKxj{;H zHr!wRjPC2QPO@t->(>)#UyCJT-dP|hCzGVi-MgEbMWd%UVeA;55t*&Rk9U(%n%+o< zee}`cXbig#!I16^#V3b>)H_B|wvv=F!TyzOX4(f*mAdhBZ8Ds1`BQ6|915}yx-CwV zsf4@p`WoU`+<2MlgBg(e1c;$YJ4kzH2^G0DlW&I&-Eu3Cty?!1u_JrpBcGECI^x7r zolz)xI}93M!=ZXx3-WW9=#NZm>Iw^m^5d*f##(C%nN@zU?I zKI!9FCpN~E{zEan&j+EZBo}*7$O03bdhMJzobL0F~h~)e8>F<4@>cPE( z;qNJ}=sejrbMIzf9cXzk5EYj>+tX!69~x81IVGRIK6iz^)WolvkH~4aiUbV`w^W`^6 z@|Gj4!yY9cc@6!op6+q?al>*IytFW+PY>+TaMlJ!6Bbcv@nzDjVUPCe3$*xHGb!KD zhXrSi9ND9%RTcvJs7s3Hbz#YYlJj91vF?OT{7a+`)P%aC1I z!%W%mPI}|Tx?HI?R-O#Tg0wK~tsRf+)0uy&J{xh5*w-&zM#0(T#+oj%dx;8~ z+UMcEd_L?9l$m3Bj~UaR)T_pcwW3fId+jEz>u!|HxrKAy3G`ITI*RWh3bKerr;Vnl zs7oZd(jF06=Y@+oB|>Y%7Fxpmt#dI?N$-L?cYBY<`G}`v-t!(McUnU)%>)gG!PvZj z`xOTgHgx|0`S@lrF>x8jKXX7b_gdFYoraW-SZq7I5T{lrVs_+87;x95%`QhQWe>z! z?_yzld6O7aHG>9jR>YNFMZz@WKB-j1z*RpUZ?sn8QN4o5cx;1Z2R-1K$UW=pTLN_DSFj_kvds}D1_WWG#RZyeYt(=K#F(jQX-kaWDgw*acWc<=i=4YQtp*y*H zRK=OQ=x);}&d;c{Unk8!XT!axJA71DA=D=Zdd0cabC(Uqw765<)Er7)IuA~LdtvG{ z_PlGv3+)q6IftN(DIrg3vyCP$PT&sZxLA~OhIY460E%5ykiuTFp^FKN6UN|_Vgt?9 zsikQDMdI8Y?&~y_(&?;Yq{(wdO#quGa^^iFVW4xQXE}cBl^0YBEJGN6qHxX>Lysxk0;DAeAf%=+IWa6-9A#; z=n_%lcbLAt?TMy}XY_h|y@=}{M~joavFo7|bSBS7?!qbJX?P4wN15PyY#)?X%z)QB z=7#hhhzQ>_nS!P{xt05h1AjzOk8}B=Fl`lkRlI2;`wm}8bfI;NdG%NOBKWKsGUgPM z%i-O0sBSp-E-t`@+}?-_!r&Y z=s=@JrV5qHVOV^=7hd-WpglaNXncK=@;bRUFuIYh4~s_e8Bf&h=|k@#tHrbXekk8i zB;2wk&^OAL*|G1$HI&cf=G>=ab(S`o#q)h*N6LjQRI;1rQq488M28*J*?yXq!y7O3 zqsVsUIL^zkxA}@I?JQhDZAB6?PPY^X+=EaU!T#o>uIP>$N&8I}h=q^qX=>B&B;6N= zMVbM4q}5GD9XBbWp^17_02^m&qmlg#6Fj3RgSoQXJ)TgHzZFrsZY||}Wxv@RIUQ`s zpf6RgD82S3_1?6QHAxx1t4_taH~{&t6=n92a9(1!|ZE4=*Waz8d=7(*tav# zy!IoFvQrQD;~5{nP}H_(ZJCfIOvkw_@3AcrCg7~W=0$a50C zE^w52ov=o7YZI-$<{(lmIz+JQ7)*T})hAL}&uqrS z{b=981j@TFT8GTCWA`ukXIdq{JSx@ zoN9nR!~G$dv6VBd+AvvZKu3GO6P+ie2)OCzMx%0`XT4O%Hids<6@SB3GV4HJ>+x#?)n~&6o-MJS`f+p0+8C z%tjtOi2U>Aq`AQbrmM2))mI&4c`ZlJ(R-+(W3ISz*oQTE11G2+)kLk=3JE#ZkpcI>VNLrXl?@XoG`SVth+n@C+w>FBk zT}3^LxjS)%0n!pm#mDyrWY$(fr^fIehM%Lqw=m0$=W0K=%|zv2tkL=^;cMdv8v9Ed zv5SfhdU5~rV=2#8meUybdbB$}+fJhSxgV)yX0dEe$vzTIkLW^3vnaJtf%409v}m3+tn}q9F!@or^#U?K zqRt!XU9?Xroz{mdVrb10JaO>Ay4pCJzRM5Gu7|+XPakQaELLx;7b6@wc=(`MYzxa2 zGiPq4bY5s1uKQEcRZCPaXcZZ=$Drr6S%|92W6*XqvXd5Jc4-L8wdDA-=+O9+!z$^T zM<51I^5lWEKTR0zgOdRg@wc}WwfHUqi*<1E)+q5PJ_&j^`ca2o3(370iKr2U%#B?7 zYpse%Ph(W|9}J~GEpfk#=<>GSSg2-&yx%o&x5^Hg4}sz%5y&p^!s@~{G1oDJOqTM{ zrb$3M$s0R%6pGyLePUDjFlz zw*XQZG7ilHBp6k=jJ{?jK~!hbmhA7;->Hi|0 zzEYefzNY0<)$Aqknifq5Efo>Yz`S3d+mQ1RE|{+^q4ypa=+B{!*dejNxa35%Jo%0C zeP^Nmbt#SBGZsbv=t85*4*MtlM1HDV_V_sg53}5nGG>=pe|CXbt2h}=27Bn$+GrYN z+Y8=$`lM^qD)#ZiRGiX6R;(eOo!Kia$I2=EECU_4B;&kV612ke$-w$81>c_vbK4P= zI$;cbzUc&QE(S5o>=w6zdz15k5Mdp;T6l>0*!#Scu6x^y*K3lnc3lj`jk+`Hcq?DTgS}drxl=Uy&woq3G>D;BN_d!@MZT#fux)!tW-U_@aykSb z8aNz&!J8qP`C?Z3J8FHUgwx4<*zco8j@6;`_nHL!;}HbQl}WfB$70WI4)bmApy6hH zRhO2$NGmy^70VOFX8dw0ZYPH1jkO5DE#*|&rDr8JTf{VUTUbWFHw~0s;f$s z0|VmaVd@g8N?dTvlHf@79+FhWd7kQq36XIz3BkcDf`j}c0^%0)%aREH=%_fpF0VaO zEA^2QRjK*^t}sxl8?-z!AR=7u|GzcLUmleZ8LzG+Q4AcXt`e0H|L>cRQn%zcAO8RQ zQT{kefhOu2|NVOZT|!%3%9rTiVVR-6s?q`lKNy{5~DDmcjj0W-NA1qn8)la9%2!@@{XTck!~A z`<~sKb-sAEau`fwb@4=N3`E;z8k84~#(ssg;AuZVh22HNrI8!oKpX0&isLf<;nm*{ zfnQo^URe}%<7d03zb(%-CgL#j?6q}!60OYw9r{GX4){&XE7xsbPp!B0A){ac*ECEmgAsNXY^8=@bCEKZd;izfFer8^_CIuoQcER`2`!>0Ha*3&wg}AH zKL+L%8lLkj{4Qz~ zhvF1>&2P#n;cxz5dSd57Co(coAT27NU&8Gzkub5q!fjx0=$wlcP{kRf? z^tKeczGovaZ@Chjtz;x4>IUKhcVfOw`$1bYH;Q|OPsQrI$ylFb$=@OYP?4DfEIdGC z`n@2H4bNz?Wi;M)ABV3`-q7ae3UMpbmfRM1UFqT45r?4smAbyhvtNSPl1zJc5Pcl00&{okn%CmuP3HA*#deaDQtZUE=>f{wjL{ z|Acc!txfFi*9VK!eDVIcJ`(pQp!A>tNY5Eo+vV`5eh8{ogu>$cVR{!K3s26?jQKDd z|4h{JXi*RPRMSp3uXtgy+%#0?CyP^KjsFzb2DczFDKy8 z?;o5oVk(Qg4}s!e`H{W*KxmNT+(c z-*oVm0e(#xghzUQX!-P-U4}!2=2~Nfo?1gklGc!ZA6IdrNef5MJ5l~33+VpUK`}cv z_2ObNxMY>xUo-CU{*1#W&Lmx1q=X>PX~N?BE!sFF8oGS~;2vv6ipA`l>1!_>J_n;9 zXDtoovqbb!BI7G2%px2{U%3Z)dgM;}J};M4*STSWT^F(XDSrc-szSO~4qdZyg0tZ# z8Zmbgf~?r7NSerOG>1*`ILR*qL;UR*h_$aW(RqG5bqfzfq|;!u%MPahytWGK8R}># z+9G-%I7k-P>+G&tZlHgeC+YAZWqP(j71JNv;lQbSaB z$!>R$XgBbt`|4wv4X}dJs&>%@OEqEDA%nc`j_56HFsL(*a_TM$1LlhyN{vT`lM~e| zD8Q`D17pq2vFuSYe!R(`n=fY2YnfX-&y9vbbs(MuJP`S>EKxaX3Hi$E)7BBSq{3Z> z&IP;^I=zop8cdmA?thXvv?x&`1fTZspnHM^p@ESGI~v<@VT_ zIRnMxdcvmHQJQy)_s3goupqyjIvi4v^K}-sPxZx}vRoQ}Vm+PQbd8)I24HS|F|BtS zN&Z&Tka&~%m^J4p>Ir8R(~i)Sdph(_rJPoA=D(?{CVQ9XVzpzma4TC$s}IDY%eWu3 zU1l9kE0dxJlcV9C^qSV4N=E&|leCvRRz5Fp2!-w8_`#VYZ)z9)9~G1NQEOZ}D8Zqf zK2SX0LY5PHVSbo0BJY2rm*PiI1Tss`E>hK72WTmjN(i7 zsF-<^_GPK#hs!J&GRJR~(SKxj|1T{xlPBNlXX&VW1HJ$LfMSfli;sJE2)(3qI4!Xf z6OBXBZXm&(xtbz9wJ-Xv&7^z(mQdcP0&#J@Jszbd!t1Ir?VhVgQFaDY=a_(JhwO1{ zcALmzj_G=#hi{U>6_6ibQjlgBhpx;y$zWG3-p_8kxCj{l*q%t8iqy9k~PKMP;L~87rtTW`(7gXY%>m7?pipR?1^jB&DmpM zOi>0^RKq*mqi34vxr!XN{<|g$Lfl}mPYrKP)9`W2Udc}G63kv^gTT>A@V2stPs~|* z;8j67emOKR`y&l+c}(}G&&9eAoR>}-hYAZv81G+73x0)RPEs+QTRWF*H>gotpeuGR zu|ug@J<$>F-!1<_3s>+Na$FD^#-F9pD|d@01DHQPdw}FvPl36rWAUbIGBqx>h2j@S zJo#pbesZzAXU)I~zp0{}yE;E8j{>8=(2&uoQ0p5_;od_ioqJZBTc(oph@mvf*bdTP z_mSef7|hb{Axc6*5%otOe~esk;byaV`0$MAtc{@yNps*5*dI!{`q<5m8>MqbI8mif zH@;YLepL}6{d6$q4xd+74n~>VDCDQ#BI|W2(6+uw%a}Lum{~pr0lDOrF%c_kzSH2M zTeRc_vk)U?5yaUH55+0sjZ89rDgph)W>u=#9(!y_9g_Hisq_SVvOCp%Fl&HfR7o*(3Igv^0zkmfm3 z(cyFa4XB2SAa&aIEs&NU{EsS_h4wT;2C>{Qtnp=c`vhq$W^RvqOdO7{Rm0TGEY6h$ zpv}w;Zyqb5B7ygBvjQZ^ANr!dqa(Y6t0}0}1+M4%)4zy0`1XE2^>vzq)JG?&!1<<7 znzx)PrmEthF8jOe2IANbYjmF&$UUCL-0dBT1<7GHwR?t>^tR0+*D@GsXR?v|RvF7( zK2U-T_v6J2dUwPKuNo4lZqNe?@zH1J_#9Z*Xkat<$wpWN;>#Za{mEwN!i~OQg;|(y%sZU5CU_;>D7s@a6*tP_ zhFLe!^Nb;y7njg3WByLz?*Euae4cePLizmxNZBwMrq8dFu4)MMu09i~DQ~Go#s@d! z5~1LhPQBF{=~U7`VbqomE3NKyA$tVfT+kK!5~C5mRgpTz#G;}2uZXzzRG4-55RQ`! z;h+7Q&LrL;N2vi&?zx#7XJ;XE&OFjOo{Wr3*GZux1k+Y;rQ2cO#KywKV(ZKrN-!OO zv;BEyJJ?IuJvYXV6PIb&NN=1z$h_uiSFGA-2l4ozD6db(hRc&tZ+}?iuNWx2rTk&P zQs6!B1twkQcarX5$?rXhm@my9v=j;Hhi#)Z%+P6?C40?DZ{#xU;_a!=27)Y+4wQ%se2_EcUM2VYpakW|(je2vjsNf-KmiNK(>b^M8 z)ePp{!fEC{-gz#S!gY%tu-m(ao~L`!vEJ-d>s>_c^5JOHcB0147<}~`j*XnhUFY?f zM!hwrsylI*=wePqo1cpBrPJwmMS=(lWXD6G8Qx}$!t1m4SmR`c>8U=P#W3RiRXD#l zRdHaB6-}&+z<-nC>HAIMojhmfMt`G(=M%8t<3;icwxN)JMdJ4KJLHi)fkL+*5dZnL zP?aK+FnUxz+F4EE*gY20dMHt977^a9i&PzYx_SXxN&~> z`GG;GJKSh%UG|Nd-W%Zy^Te8ee-v_R{e(~DKv=fM(#V2=Xe@U_jG7nqa|_1t=nm24 zLpTlCYl(}+Gm*c-h6WUl#EJehFnXUlr9Yd3Ze8?f(&!)xeUybjPtL8p+bzkxXn=m) zx3#F*N&bI#(4}1+gq9xE&fiZD-G(KDh`qr>8&Ga{0cU2~+5`Te9*ccroH=3`Rze@+!6C(?qjWDNVst0PafD{0PzDw=~`61ud5#{J$QQSvVkcGH6J#~=+A>uN>0f+ik$+T(eIId3}$ zF=(w^|sFXJ>xuJt3AmD7;c9xLv= zFoKiIa8lb8hT9PWe+XLx2dtr0wqL0D&jvAUX&`=0D;59p7TJ}lw$r1KQD~SE%Ty;r9N;Ha zX1uzctXo$Yonv#-o-WkwO4&#O{6CbY6F~Z61w@KrQqNJl{Exk&C}EiT0*F*zbUdRl69!i*G?)a0-kDUk`u@h0QL zW=ABu|L<2bBci8ArSfI7O*ImsL&wnj{sZCvvj+v5%8}gc*=XNvNJqKE>Ui7*!;&>% zD`$Xp#$)Ni(%G2JQgf}(`gq#q9%W6@gb9nNomX|m+&2^O-Z>1DI(N~F(W6Lv27f?k zsv&PyBvc(!C^fR2)=u{$E5+Mn;*duxxA6m+muvkdh0?{kGvxQ6E8aL5z_*>y!zv9u z%C=Kpaxw!?x>51fTsn4WF(oqmDZZZs89Sq>*}{-RIpZ)RR0fN`UZWixoJoDKPFO#g z%`gx*X!XvOSa2xRPv02EvJSL?i#K<;G%RHqPPd{Hv8wQ;7;`}rtznZept_Fk@3*5g zizPIR2dlp}t&$8Z-~w{f5SUx}!Iy=-<8zJagTn@@H%Y<5Z_!YfE*7>U88UL1;S)`2 zSP*=LmYFP&Z2q!Roa=8P7A%p$l4lxFT3t%1K`en7k}F1ePeq<`IHo?EPHFF-Qs{+1 z4EV$F>*2%brTJZwRhj_TFkS@I9hYOgyM$s_ z#T1mX6no{nSYdqR|6MkQ|9>uH1D4J4Z~ynQe+N zePlx?`I&G$+)IRYT%fgg50G7Gq;NBRO*U()XwABZG|eL#4tJVp$()rW%L)B;Q@SCP ztxU^eHwe2QoW|$vcf;G^XjL45Q1v|0i|mU5+DtOm@Wl2HyXdoND!zCIA$PMYQhz6t zMbUj4k@Alw<=NrZ`Y!m`^h_)}IG5f^Gv#h)o2XiQh>q{{!t@il63ApoE^@P>X|WsK z-2H{hw*lTG41w7h^!HIFC;DA6GWZ2WjF`-J;#ExUSD{m~hlQeM7J~Ad=?>F-BvX!3 z^RTV7hX-Ka9JMgz!Vx;Vn77~h|ES5RjYiM3#ITjNG_aoO z`wDHf>?Ea39Tcw3A+vZFiQ^RoetVeW(}do5^n$mA^MaAPbRe644WWG50kgcfi4`L} zaB-;tb^g~!qS0*-ZiVS0l^bwhU)#bd zwL(M8Z`!3h36UL+a89{SQtv%6e#H}dX84wl<`09r)i`XQJp+NIoTF=E(D_NIs`4zm3eMMkJ@2M8r>x2oH~*F+Ig(W@lMe9NyS)d=ZUO z`b@PqQbhLhxzyGgi8*pT@SkQV4Y%d+e-6W4)>hKMrTJn`uN!nJI|S|Ld%)!O7SVV4 zJW(;SCknk^(~h+X=r%|PBS#;i8PEUF&RiC`yxJ{J%X*P_x-<@~JT3k)nCrHBHNBX? zJwGo^oMb5L^_gBMzBLQS-zQ?s=aDGU@`8g!Bt?{@K=lBNQvZ3P+uwflZ{Nd%Z9xU&kGlc~YgGtkv;SU_hdBMQ8jO&JQoIQea{khcvax6>3dS1^hR)4qnR8n*irfaE`Q0GoYW$)V?F^0ldWs8lHMUkgYU$jsUbG_a zI#p!0QOrDldg`{EZp$0sPFojL4=WRASN4NOe0QA6$Uu_I9eSOqM>CEl(iXY0 zEpanJOzttsj3-G*Z;)o!`T>CJRbWGc)(!j5I79@B(^r5A$bn8j2JqJ2jQydafCsmJ|VEb-xs>7 zV@R*#EQREq6|rpv)X}_wZr&{rdpGg>V~sh@S^iG!b5%wtAC{G4OQ_8!3o2s;41cT> zcm8ugI4{i4W;9a6$r371+fA%{@lZ^HiuKU)uvMrEav=(uKwFB$LX zp1lDY9&Moa8-e-*`E-Sa4l*4B@$S%P^4J-Mb+tA~>nNq@l{P~4REs3(KR--3>Mo2| z3=>f`yQs^eO1(7Y=t&QGoRYmk^*?oyvOg1Vo1-x{-I^gq=BQE2hSw7#(e`Qv z3O-(=_o)|X{sced-Wp12UF0aYC;=Py%%;d)F{pgGgSOw8ikoX!QS=d4NrrQSNIS4o z)Za8lpedK#Ji5@G|NWdeIGMYTEfw49sP(`-hPe5V{yB4mmuS(Z8ar{GWfP8HwJ}33 z9~8MtzAF4nf_&{$q}_Z_{AzRlYy zc39Vt)uBx4>%k%m$8h)3-MsP5BhfPjcUb*w2DKO2EJop(v2b0gKOxA_XV=bE1)*DK)f$VrNP6;pum9# zOR*AqJb4Vd8_F_>&l2XJJn^&A66g7yJCn=kCdH+~f0+u-toL9*Mn2t-9D@rLi>V=` zH=SE-guUU3h}K_8d;32XUrv|Oy+AI$%}=ti=i_9V^gh}-(*}D?Y?1HV9hPgqNu2yb zFtJN00}Tej+jJ>yh(AvLnd5Oh`x(i0?}-w{K;P5JYsC}rSlZVsM{A@gF zoM|ENM4~=rTuyDTushlBxcEde64`w$3>|QYOa{(DY^fHqpN5I9dmOO$@*21NA4)@(>j_%4a0}&f`KnVd5iT+;iO2`W z&7V&fHz`QOi(6!uc|cs!E~ejg-{^h89eN%+5?)o>Sl(L!Mk@{QiHAL>(w8B&?DOcT@j1HHyoY*P z-=P&JQ|aB*4(i@xDgRk56y)WILrN2o6h9MHTF!9kH5XYtcrH9llJQMXDcf3=G@@8w z1A6`@4- zE_{$ZlD)TvP4?a+B&6)j>UVvA|A3d*)BAZp_kCUGc^u^PZ77R23vu$D5e`QbV90t8 z7W`yl#hUS0-OFFJ?=*q>p5bWS)&;*SKG6goh~B%Gj)f!2=}3DXDzv>|Q0dB$a}L|r zNRyK31WKNhfekB+#Fg*?48JX<%=V>1Ws1Jbmb}mRPj)eEkQ?yz}1^WxQfO3X` z0q>jXhKB)yXB5%t>K%`h6>X4}I0{c<{ca}3Ih zT~I`^c%og5%#+*1n0yBg+J_-FHCy~k{v{F>v{5eWN-DX#Xs$#ST9aZip;tRCP1#1P zx6B~5?)S*%)nxduo=IT?-_etx58_0J9Ws1*8P;E#7FRIL<4+_yr+uQfnlTiiwutga z`eOCMm(-$ih#F+gv1MHtG}bq8Ib6ab#C&ppIDzK+^Ki+zoSr}zbLVTJ>$L>hy3|Ij z=^r9#9UBhi_+OIzMF}u9P~zoDlrZxQgcU=l{R^@oF`k6U3$F>CoH#^mGR2|?`YfjD zg2yM0iX9CpIOCHCvxBkt%R)cTmHqMWQWMRwQo)zl7$iK2r(g1NHUGrL#t-Bv^GMR1CrygAK<++cvFS`0 zG+%lnZACaVDxT1Wd0c3EArFHx9el6eOp{y|ad1r?Z{EJ7;=E2#Y*A0IW{t!6VV!jC ztTKEo%4ji{ol+axXluJ2ZuWgi8<%n`PBjDGe#NNQQ^x4`jgm*+9b6y}qIsp4>G9$5 zjqzN<-FS5yO;h7{?|@%)zM+|1MiqJu>^}s_c?>1^ zTt%IyYUqx45k7I5Wl8ZC$$xbbTxM7)d1(Jw^82fckpHX;)BWQy_j;}*pxPbx_O7Pb zz#kOsT1CqgJ88>Ntc4*tmc_@lcfzpE5_V{3O__O1Uc6t}11hO-C%hC^(k| zm`MUIi7(0h^ItlbWl8BPb@Ac$Wje(ovqc>8xuY_J+DvD7?TE+{zDZW}sg5B5Z281ATt ztZz+{(Z9}7*MXa9SmA40as95B;&7giWc%RE{#BH`Hv*$t%n{+!9lO?FAua1*bPV4~ zrg8^q(Bh$_edQMw*B;_hwI@sskCCslFG3lNru1 zj@C?w!Hk}x=@NfNNsD&TXfEspy;eu*>S9c?2!t=ci%zL3A<23VJ#~I9HvZ}^W`D55 zmy8a|@BV^(cH9wt-4(F(%nkZvBaPZooiuW118MzC$F#0}ko^1=?d6cwxs!?*a=1H? zY`{R*F3^r2hSC=$^sF%!Hm_Q#J)G|!*73aLA1l%o%0=PQ7>v4ek;*s9VtNCEPQFiu z)V3@fURq4wLvxY$Z~Oqom-9mlo)LLz<BR)k^PGP_2nWpjA>{gRi^D;dK2gx*Wk#fDXb#Go(-4Ewp5vgbb#Mho5O`_CTe zmmh_W2zSIBQf2{20T$VN!>)${4EUYY@6Rx5=AhE6IceCx;HxNH;!ByOnhb${OMOiG z!THoQDwIA>^Df<@iy9dy3Vuu{ey*nGJ`&8}IboNj_a&KbV-Zu?4d$10aB8s+j^@24 zTWfQ?S}~CPZBI&;4PXG9t17Ks$mO`{+K3#}ADN1#*giOuX60@ZhbCPV7cQHl+~u}t z(0xJa&*iaTN(7|;jK(CE3C+v1r~7qNFrvejZ1>9Hh;tNfZ3`xwJD%kEF$70W^0U@y zg|_2+y#8F&BfXqOl50(aAm{i=RCoGdUv;a5b~9MIhJ(mEjnT3FCsk_%(RXcMsI*_A zz;1hKfxZK6)0D@2ms(2pW|;Io{>?Q?qs!w)!7fh=yYxMAd=pm=l1Z$3Opk2n(DPBK= zI*NU9x`JiDgGQ1AkEDXNmWn^mxV+P#h^%v6$?x)E3QbCZrAUK^)hyDTITibCTf~3c z&WI%!`ce2RYs^sf#K)IBChyC?yA297$+9b*$Y4=&i7(PlN0HifzIQze#Ku0WDCplX zh+bn5)b>FnOZ$qraXm50G!+|_S;(!&63X-k3G^iVrF2 zxFUub#N)3)e|)^zo9zC45sLTLQ*3A<8XgSCx#O=X3Wgw9^_M{C*&?;}-_?JN6ZCKh?utb!k znc>EG9bTGqA)7-HCcn&a*u0Y#A1uaejaDi;ERXdXnHcJrh9w`JkagRUy3UfquFs#S z$*B*S4eEmB4=QNnK4%10gyX}ochvRU85EA8UBLpe^`xC1 zgec>s5~=p3Vvn;L_IqWayNfF%EA42yr5Rjy29mn*HOUT!uuM57hxvN`Tgk@8_Wc?ot9Q9sL@8(;>hT(Pn z+}da-ivWAqCE~;vPfQ-zN@a4^keZk*Y%->bMqMS^)cBk1HU%*tHVEq&#%;ZIB5seC zh3&x}c;P&r(qcKh{mTJ*3C>WuGn*X57(7#cB|I8}QO1Iuh>OD^-^zfTrO}YHg#9c9eZ8FWui4^^f2UC2ZibMd9+>BK zoFcy5r4?F@RCFU23LGX_eqP_Jr92cZ46+;PzEh;;OhMZ1JSZ0gA=8R~m#>>Z+T@G~ zZ|{R+d-n+SPyF4!;s>3h*XdGYInB~5m3)#vMkQwE_^oMx1LTkR4ZTrYd`{A4$q;s< zSJXaAR)jCpLF^_uX!1RO+c#zO{*!|7zEjX!ah13|q&rlfdgJXYS4=SdMyc*q)WQ&~ z_OlICpQb{Ktcz&7(@k;b+(D8&nojR{?)c9-1Xf?NU?jCm%qx3F`dc5--yQ=nTyH=5 z9OW|cyiU@;q>Pr8BXLYC9B-CCptBq#R6HKfvo;eXheToES6$Sv{X%!T_v3KdQ2aM_ zEN*F7lbNSESrx^>YxF)bho!CMkCia}%wNhdH^&c_yv`q{P77Y;lhw&7ILd2@^V2qq z){~bcb6XQ3*PjbU(!G#zTMif7n#F@h*CjpvaPhCWoO<&}ebzi{nA-P;>5XwX&g+7d zJSmLy^Mup-0F)oqW6{tQWUHuPeQFD7SjR$7@|~tDsCZTAEuhWatnu>RFLBq>1G;0U z3FrBfF=b2>wXfYpDR+IK;XQ+N`QENnYy)j&Ph{ma&gnE@erlCU_3bJ(_bqQCKn7ekPtU@(9p=F3UBd?05d#%vk=8TlC9BP~QgpxJ= zBpMkDN$&4B7+=vx#wjc4ZP(_KM=-t&H$uXlR$BD$T=$t^(}e!Ke7*bz=B%zsL+d11d+I}%GzPovQ<^004IFAPIIXux_JuBwSY ztr;lT!s767LmZ8a5}umG&(;K}d@I1;Ih&}R#fbnMV+G<8B8MpUn$ zxn*g72v9@_79V ze19kti*rKZkkbd+T#_t!Y=b3z>q(B`a;EF5=n6kmYnvXC{D1i{&~w8Z^9=EQij=r; zmy0;IQ8e867_IoO2or-^iG7z8@$Rq>zRc*!A!a8;Z*qg}n*?-sU??d=886hhV$FOx zTzU%Hba*w59R8i0O=VE2TR@RrSJTX}OSEA7Xt6f7nHnB>V9iSlj9bO`rg7sjCX1oQ zJ?Dzpk;5=3BLa^bLA^5ySzN!Q$9rC7ae(2IE=`H3OWREwyF`%^gK$F@5l(bwiIf6OXn9MJ zpgbJMXCI?@B}Ie;nIW}~g(q>zWbv#!J~z#$-;$#Y1Aas?SKY~fqy|DA&FC^^MzjA`{tA~cPzHW zO{1R536T7-!?30QNWnvg&b}?cGuHr&Px0q~QE$9t*yZv=kLmG>?)1WOtK`RW3I07( zq?0BsG&0lK1;L894S!1-l0>qSuQ4(7f?OOw!yzA6>!#xdHT) z%MiQd@6)*JKgjjb1DbCegQq)WAa|!9HVw0YrCb|5z7&c__1A^sQJxhxa2V}XKCbiA-(Dg-{?&-Ne|dIb+dB;*4pTQU&d8 zwZ;+|8>*a8Di(R#BjHyp!__}CAn7h8<#$8vY!g^}zNTfqN(ia4#H!hbw7Ty}p>9_x zsoB;a4n2(!=xK@1m(8$nmNrAH)3H3~DP38(lPb=8BI5gd%GhLu8G+f9>m7wViB8zQ z_8M*dR!#OR-_ieeS)bPjVR}vx-8mnG+o>t2k8^{ObQInEJsvi1b&&J&K5g&4ixy~q zp>ET7PE|Y_Gk5#Z+T3+s4M7Sh`BqHQ4Sxx9mQ$Yre??7yE(8V-qW7wqI2-H?&zM5U znf)T8>tm5rY=!S5^l7y5fnk0f&1%p$=aOPKSKO;VN-I1A zMP`pjG%UL-f=2UQs=7$xs`Hbqb{`R=TT(^!rvGT)fmm_!odeyw@SNtQ4WKPP`Dpi) zBX83ev~6!Zt~UwfK2X3{2M+JbOJFu804MXz#IuJ9$T?FCsc~7T@ZTzQ{9e#0;{d#1 zxk1s329mK@N_*D(!|+!LEqC5c)rPzL63u??u79(p;SG zW+HUUCcy2X1MVCvqhyUSP|skI>CN*J%en>@(~ZIPC^gtByr=mlbHpdT0Nh)xLMvE= zcxXM(g3fU<_QyVY@WdSp@_gZ6xQ)g)aFO@FaqzWhrU#zJ*ep{*WuLSd9P*y-{%exl zn3jNy&%KfT#RR=aq`)2=ECKI5jH|e)T=z%4IYO-JvI4(xUU_GyRqitc>Y}a%V+zyvZ@rx z5RJi6o4r~#tQK2KT`8bp9vR7o;R(ODU3wTGVUP!s`wqjX$0IPXVwq&FTnl-WyNW)1 z?--+3NsU_{(_EW4jQz2P`bN5<#%&xP{dUD-uMTk!C#gq|?Ns%Y1u!$O($Mua^kah$ zCBOQts08ZAp;Po-a@(csvJHI$H%PRuwUm(PV;t<+rT(vrFf8h$p+G^ zNksKWDGYJbgWXXbwA&|(2g3}I-u0@vRLMJqk@i0dQx|LE-o)ec$u;IT;sc6a3r)GOJmv+^4i3~+$@%i(x+e+s^itEQ(Lw$b~2mZ+%Zd!U0X`sb&JZsk2N zals~vSv3NhSMQShwJ&7)C4ol&^}?Us5s*6Xk7fC%NO8Y3UNQjUQY*_L>Q0e+>?Qj3 zl99S_$jy{X8= zjW&%Aqq-7%n!nct54aTGi{~vqVJk>F$c@zb{m^KZOc~2M>5$84EHRf*?;cOdNo@-5 z4vB-|-hJZXR0jFEcwunH74a%K5%ISgnSQMWwSNc6#%nRrkpx60@qQ@50#PjYz0=_e znwf;da|V;_3r}?Y)Jmr$z0qRfg9q+==!C&j8nV=nHf}4VK3W42*iRN6`jxbb3;O3% z3*pZ1s~O=Fk-Q`h&rA7iQ1_Ps6}<0dP-Nd5LA1GPH2+;?aMrh-qCWFXJO3(47uw;# zFMp)neJJGeR#NXJUC62aw&>{PiR1MXF|2(w)bl;@b}djQqld6b_M~xn5~4nV+~)M7 zz+e2G-glPFy&2|H{fWAt98HrMu%l^j1w^qdtVc7gvAaQESmHB>vqv-fOCyB$PWzt~ zBId*esysg#@$R{}o*ho%SN#z&)(9cnig9v_Gm^)0S!z#r8gkL}wDlBSL@!&~1Hs01}5&Lh-kU{$%U6I-w^?La9*chtLt(h!ifGb$OShNxfjWb=%2?LACEy~-{h3VW zd>0w($Y)ini*&m0F)lGCBHMX0-T9=9;*=t~{oi?!8GM&6C)wa|o+t8o&wt2OVCgg` z1pJf7wfbm|uv#EnW-gU!%7T{K(bMotH2U;YGJo7j8{@ms$=NYTQZ2%2r7nmH*emjs z$3jNK5j#J=p+C!ez+$2`dbCKy8J4>hIQ*uJEiB?pj>9c?&Sbd9V9Ud?*pq08k{wcb zpP@i0qgpAc%@r~_PD19bKKjm{KxwtAxTbi4s?P49lOb_9{hM&elzpTWPkiQ+bSk83B);e8^Q0fT1f;ryPILObZ(Q6I=! zrr`YYS>o!_V)T48gBCthfcde#^tUqsCWEx0(V2<4*H+NF=Be-~(M0BkDR?x%5SArR zBzeP~F|>OhT2V8QAyJ*X52i)9iLhLT35(^m-xO=N4IOLfaC1;F# zr_@oH%CPglEN|lP$eVFGXc>7^GK7t)HGBspzsdt34tAPy;UpRZy|9K&^i?&$(;q>4-bD z(6tX-j6TwV(y>UC&4Jz{Bm7mh#r_Qp>>X#y0P=rS`gs}2SQ$}up`};nr;!Y^)uEd5 z)71L(h*wEJLyBk>^sKi%Eb^UU@M#Hk80(^&BA<lj4yuAbg@&S zCym`G^T}hXA8U<{(ci_ohCT?X=z%=NF4#5ds+ht+)ZZB_T&@^}+9zExeCI~;ax5il zmZOHNDZ$xj0;=~j5JGTybmm*3Rb_?2ltZ5sT4?BM34P-`V8MYB$ycpDhw_Vk>z* zBnaClI$`0ot)wW)!1ljUFq)cz_HENB_|tVV-QOK|4x326dQBCzI$g158Gjzv&e6y6 zLo_FoCCpAc$(n&=272o7+^C7~*RBZaCJ&7xHzd`zgr_&x(EAxp^zerkA~OW~dAy*H zJB-MF&JJpxQBN&NO(N6fI~`xa)wgA@X)r@Be>H}p_(B}E`n%BgCyym-!ZT2HR2OHC z4iPE=zT)X2XPmrk!bQ_1;z526TngvV%OZxr_47u|2xYqPf#se%eBgB790Tk8@iQ|Y zRjHm>%oPi1|60buw)BoeU7CJqV$kD$}S#@qc@H4*=3nXyUO|3soC_n z>NCA}utV$@J50GWgFHW&;aR3128YJL{we=Efk&w8wQ|}Oew6YgE5T46hp)C9c z1t<#!kL;q{>t{)0SP!iHmI4%yLV6QdLZ-!FyZQ^d9TSY|peMr1{37*|HplLtO_cFy z35~Xu!I`OhsGBR7!p&9T8qrD4y8{q0y;hV=&BQtWE}pb1!p;@r5T3M)jH>)0w_zT2 z=1nKd&J|uaKj~m~bP8(KJ4N^4nPOg35gdAGqa)Z4+DC11*l8MVznqR#lWv&vSc1k` zER%j-j1PXMB7N#@nyEVl^S4bUueI_|dq2NCi*ITj#&`jhdnSGqzoM{-WU{s=E&zE1kB!Na-gvP`jJofphp-o*atLen&{& z{1T}IGQ23-i4t#~7UHKL?Vmpp-?#R`ik5@qa?k~XUN+K)Rg+P*I3A9T$>OvOXZx(O zQMfJ(3QJ{ii@^#SUvg>L7FiVESSi6EFN>2`Yh6Hc{V~LvV$m09oOc zUi-(5L*u@qG>8G$D(zXMb7m;_Hj3Hj)C<~M(@>=}7^*Fac-;4_s9?EbsB1DD77T>% zkO=&FUrUPjBP3(H*wRRrdaPLNiauvssoTo2P}#RpwCP6S4d2bW-AblRUBVQNV0d{< zWJvZb(XDwsh5zC*Vf!^2^h*bq{eloKw~ihaF!X-p78YbB>1D~JLD}KII zSO)Pv$%uXrSV0$6ROv=n1;mBMO1l0@mFT|cgY} zuK14b?pRHaj4LQ!R)P(jwf2kgA&W;cc(OT)9xt6Cj1n|R{qQ#O;s0Ck+Cvnwt(j<0 zFYNTWPG$z$LWSQMt+Q`PK737r7Jp_5XPi(xw4H`7s;s_6bPV-zkLgs_1#MdHhQ)MZYkD1GHB zN~abhMCA_k>Uo;1Pwy401_Yw;Pcq*9y&xjD%VTDm8nP9O;b(n^>Wa*<&>1|BcO;wn zzM>z`c~zG&09{=bi_4tQvEL5ww1Tl`iaptvyc1S?D#>i88||F_iNe~3V(cge;w4`a zZRw7*?QcH*Y}Ut|ZG0zfuBWfJ=h3^ZHk`?HV_;De%~E|rt_-rWmiI?qt`){DlEy5# zGO_OCbP;R5n0ge&V6}ur2JzB3o4kWUjN=f`@ZU+6e@Jc9K&l&hmB#i@rBh19XtAm! zk3$7yV04O_x^D84o-tQcF6l|X{tYCr);_4aGgx#zsX|?RJ+YgiZ|*E6Z3<7tDy<#V z#lV|0+Ci8!{uu?G{!Wj7?jwg&oL%=fz%}_O(Ra;W>aURs@9}liTO}593jNVE|1bsc zY;uq3ZLjok18|sFcoK7zA}3@(L3%VT3D%+7(lF}d=8a$Tk5SKiX*Ae|C4*m#Fg5ry zO{uZL-Kl@6Df^qKVBv7(Q$1+UD-@bj8J_m+1~uLtK>j!7VEjB94mY`HvP>Q4=l)04 z-E=X&X(OFfjiWBF1Wdy$G5W+SUuCcI!vt~p29DdvzmGA7ZW@akXD=b8j`XY%k=abJn zKcefm)KK)_dk|QIQ)7IloXjw20?);q_`K6rVy7xs#`B=Pbtq@yYJBa0# zJ0$w$zi7^_XVjEy38MgQvFWu8sc}jlkE$ZGHN4|l<%yds zyjYYxTq1AvgvD|Ug`4V$r?+&-zF`t7zxj}|XDD)#mC!MbWvgwY5OQKJ9rtUXVwJv> zu$^HSBa09xZ9r=bb&=b33cjV=U|Q8E+E;dz+W$FYa1R!oW%KTPKTCj~ydi_nF$gwX zFIlFeh1rse-h~m6J#LQ;O49JnR-;(ehoajKd9?AYBlT@DY^x`WYX^5z zet%`m^0q|H0SD+jo`RQ1qy913l)6~-6;BVXejqWCc`P|GX1JxI#&2mz#e;C zS#prxM}%V7wbOJY$OOhFzId!M85i^kaRwTAIm!WNvNdt$n-Qu%c+v*#6Xes>OjG0r zV`{cG6giV4b0SN)y*3o-iE)Uu`c2&qETxKN;~C^_gr5DE3IkJJeB>G1TF(70G|@%b zYZWLvZ=~FiW?^%h<#iW>@ca_rOBl32YV$x!_78>FBad~r7l}UU9yr6hn?J{tATRBV z^$+4mWK9D~+=2GcuRL(ZsLQumvBm^r&E)-Mmowt@Z_GNpL7AN$* z$sk_yb2RwUcsk4H$d_%wSk&byRYw02ff)x#YhgN8yje!S1}CB@-we0Q?$ap-;7HH- zC1zSqVL_fHW%BH&!zq%uZ;wa&E9mslBvG5E0gJ2>^4v5LY9m8nJNrM{`niTo)C+j$ zI}~pRgi~3Y1?6(btX}sU9o?*mtr4Z9^Cw!Qzk4e7Ec-|4qvH7f(nub5)tgt$rKJonCdi|Vd;)rS4N;Nq?P>7OyaqNJy+7F@eUy#h1_YKDceF7 z7RTuFk7YDluSOVzWn<-^YH~aOPq^&cEmqF5gTWnR2J>W~dSwA^tuCOJyIDvso^T<3girP}b@OR%)G4((O9sbo9cmJFr zHCYBSH<&|yjjI?haVOV4rL=f3;qY$-v@f+s0fS$Dmi?ojEKW{edRCY%uA{6ImnEvN zS$_E;3u=w^l%ijVXEi3m-<$7*`VsK#d0WyrBny}B$BIxTcsQN2Vg)HjI+)ZzH!jhKxpxr}G)g*niSh9C^Hgtg1VxmO8kf=Yzoaqp|M5 z3o(8AJ(5%mrCEb5v5>#}v%-2%ndddiIJ{B}-PjH9AIVb2R~^`oS;^3aD-=3tB*t_b zPmY@((u;kB%NM?h^*q0L5P4SI>d7;gZ)#M^71O7m`5hQF34=#1C$&cm%XPX>eI4(L z=Sxc^JvSI)=a&O9iDPR)=8;2z!_54ZdWA;@nnbS@llfsetN0nui^J%c$E4nkEyMtOWsA%mj z37%?3O-3s4t36BaXI~)uHC8C7i$qXaAkE;+{kBVcsnUNUy=jcZiu8O$S1?G!>=XSS zyPjq;fO}~DAG$W(fIczES-xcy6-!0a4IK;7VBtV7PTZ$mnnrjqq5xUB*?3ylA+FE8 zNEL?K+zs0-(yF+}qLU7>!wWU*QmHo4nl`yEre7EOpx{^_mhrQD=1l|+`rDwY#8PzT zE)?~==ggGm8B2U68A`pSlK2$(n=T}~{+VLv+a!|KtBI=uVi$xi4$fHIU zXIk@U=2FgLgpU%FrcS3HhksG&-Z;FQK9IUQcU#kz$?pK|(dA)IvMclB=S+dP~0E}BCh zen)!Aj*rF1%!73Nr7O)=R-p-<4`{0=%VD}EK!)d^n)gO9U~vOY+5LuAJmdU9-5B0w zH;G-}hM?2k0VydX8HLds%NEa|doEEZpD+Yb%lWtI=1!q!QbLo9`$G~vTo`fg$UJ|m zCK9D|eZQds6P zGW!9_sP@A28iDW-9qd?=MZq_8@wcf~=(z;q(N}e3NpGghCQkTojSGHub-)V#ZoJ>n zgN7(b;PT7`_VKx}Gf+Wu>L6U?-hkEQ-&CFdmTrFX#Q6P@c&?d@0dxDqoh7TaVm#bE zShTg<3GWWbz~HYv`te*pg}-y}D`wG~WxY@^I1E9JLot{4UZFbH_&DB}MaiX9WVDWA z^z{+!lSf{iQWTXI&Cqsd^l-XCW)|LvK06p)e)^EZlvq4gOTanfU?IC~Eb@=#*c2im z%$GVDBE0=WiuheNlOoSw6*98g2$N65yo*+to|j22^=rs^TrF+y?m^O9d?4d@iQ!C> z$nPiTw|;ozOK>r!Mqi|yV^b-1=TGryS22D};$67%A<5Kl((?Js#IrM zM2lM_GW6smtLGOY{{C3LF3&58K0WG16b+&G&?ICFLweQMyY#)(vvE|@3$R7{aj zd`&D|{+N1AnM}_DdA_PBi*Kn$Wb*Tba52)Nm`90{lttX}c%_8bT-3^ss@I|B%3X+g%VJ7zuX4u9@^G;*e~r*B`; z>+BxVSgA~AS6_;=C**K*!(sZnp3j3L{ivud5^E3drZHjRu>Ti>vH$kdo!7lYJEIEL z++cCdp84X&`W@srd;uj5SSgloy+umJ*3g)ej;?tQs5+lZzBc95c=#!07jG92co&>8 zpbLWMM`GH5Ym~iyv6r?=4A$A7CU1rZ+Kjm`8P55@&D}4P?3iW-5ouzehi`zHRLSA@}GM@mUnhOBNR{VirzLUsT) z2KAv$N5fI%wVob+EyPIMVsUoc1gum|qr*>z;m_9^(u(6<`}BSoKAUG44=3P!dl4E_ zIg5YL5dkc4$~oPgdd%p8Y05pQHsmQOwYAfq$9+htK^4b$C*WqyUz&dOD!Eu6p#IYN z2#>bH(dXT1(x)GkHa8Kf(Zg_V_#F|+IjDj%8|>*Vj~|L#L}}lC=-0bdtj%$RoXQ6} z-V_2?m35LH_s`SfYllfugF%%?jc}Er+P+$8P`U?nIrBfLpbHNCClCGbo*1_y9=I`z z+#`u<7dc|6gF7-fqt$SP;d@`>5ph}p<>PM92uJ2voc<@iRBxrtxqwSYE8TRwLQQpV z$olOWaxv8=N05j_zTWKX#-d0*7XcSN@k8lk?DMnx3kV3%y9CRb6- zzO|H+e}xJ?G%-4bcdHxvA!?%uoSGdFw)F~ev5Y3Q8PmoMmfU&Qq$mUKD=vzK)eI-h z>2jHzWsQ;cZv*Xg)kA#!5eirugu5xKa1dTNZ}f{u%?mg9K9>KbMUq?G6Y(?qQoe~lAp&E*1Uwq2t8y)==;GLxb~mMCQb^qaS4&^Osc zh5@sMN$^1Au8$L?yWa`NhEZs7*iJ7d{g%wxnk{KuHjew0r>WB;3QdYy_}$b6hH*BM z{G|nO_w%K(hxs?fv@23Qj95fxj~m-{Y1WQjh&OUa<5>wpKTn~z{msM@zXBXJd?h}a zjv(`nU`T$s!EA#b3l96xas5naygWyy{A@aoctgX}IJf&H1}ZO-AX#D!w+YKd%jynV z^2mmk{GEy(vHvLUMiT8i7A8usIKi&xP-yDeq41yv9C6$$dZ{-uTnojwr_K zjDwVWBZYN@kiXm+F?4P@U7Zt%853rcRK+8q7v2Mbi3@4)&OW%{VS`ca@tDbA>XUvw zkv7E#1Fsv1z*p+{_dr(cGan28KP~in;z7C@Y=TLZb@Wi4vl4FG`OatvZ3esctXe3p z7j7Wz<9TqSKi;pbqxw~Yu`T^2*{!LigU*w2#p@px`1Qc;ujZmsL0U}o&cXp^ugzMP z#gO1yvFSo4Mo5RD*7`8DmdRqQ=|-CUz#1;C!=Q3%2TA8!QcC?F@wgxX%lOQ)G%=WV zxz&qj{z|Z#YJ!cod~yHIdy?+2jvp~;Sa(YcrURy6rQu$>Ic+TkzHrCtGt)&B=V{CD z)$lVW!Oo^>bpKQUEImAEK}oRiev<1obMYV?TPMxHUMoD|IpIfszE5}Z>@o5KWz9>$ zv~h)WhVyjYBxpye(~nr(m|XIU09 zus6TEk5hj3LfV_&3zaQkbdxUvw+_U>lA-Xi)kKM@Im|u;(`w%D#)buBz8v?Y$3$S& z<4OE~=n2{LhUldvhf^;IL%#OG63$qxUK%9!_;N>RqC9TC&_UcnbM(13m=cdpq31s= zaPzPS#A_2evS%i>d_O=J_wXKPL@}H;%0T_#XQ5r7h*65V^wMHAxuiUz#3Db)B&pE4 zkn6mE=@4&r&7~Q~x}wVoJ#_3jD6|%YVNIX=)M0XmeCNl~;;qj~eQG}L8NU(ox~}5) z&i%rFW+VkZ`z-!D>rXf83*mTTFNK};rmzdg=vI_K(x9o(-K2w+j`m2;D-+KhW{`*5EWCB_KkysAOYR{wtHNDW_9Y!@H7+%f1 zimm*eu$9t);fS^5Ui*p`j0+Gs`zPbyu2{Hi?@9hLs+jA}XY3yf#kt1u_;1*IDve>l za?*49dWS#PUxP#}cMR@w{#t)&94-cRh5EY=8d`3N-#+Rr@!mxNSM8vBU6U$4HlA3kr@!Gq+X=zdEH z?imi)YgHu)8FGc%?lI)mU?c5S?x5uiT;D9`Lzj78c>b<3B69Z7vzY#{ecmc5NR7eW zfPd7qAsQZq9#|b`LW$X~*fQ@SyA9vaDmJu`?oA(fw@#$&%sW)Q+#7Ny8BJ+yjPh+IoWJrC<-M7!;d+K{s=TJs&O+$r zMd8J8H7w}l8p0Mg$OXz_!-cLem~2Idr}#=T-hC8HPDF}ym;PAKJ+qOX*J)q$5YGFC z;d{k(s$AR^#<%ULxnwxbTgy=K$H$UGRkOqvwpkKXU?&rX zquowZdb9_O`tPR;<_x7Z>q2`OK%JI;fdcHkepgNK5!HL7%~ACGlpQyEI+aN(*IF( z9u7IaZ5WP*2B8uy?Lj4J*Lzq^1;?m5VG9X_kw@m$w>mE69Y~)!>hy}K%yrg~}yjxCMEX;4c=DXP+s!!2^L5D14 z+J<3c&PAFxp$Fz~{YtaGjDdah5y_5R2m1MMqiB5ho%WnjKm;=&mQ|ggvA6U@msN$h zxw)Qm>SZL6Dy4Tn6rBqTC*j(1=4cK0O|6|8A|)<@j;tKZcRN?uj+9`G^)SfijS-6s zwGpqqU*exuBQC9$<6e;-+Sd5Mw%k_iu-{MpEp0{Vn-H{czyHkYEo5xxj&BVk_>4TC zh7{SN@7A%T>8wOHE>khLcOP&P7JpwRh$puvEpHNskE9;Amx`5r ztZ4d}PP*VNgYY#B_BQE*duhAcUU|DtxGB)^{>j3fhDtaFO4 znLnnO5jw~Y{XiWI&u+;-PTMb!#nXFU6fgJFrFRNq$XN7FbHmj1B~-mflWzHckz_Udi?i1~;Lx6i_N|;{Yn>sij|Res zXPxizLnz;2IgRbMk>-EB=kobCgL}W0Q0Kw@qOp7_nT{$X{hDlSUeYXCE9J-;@gyA6 z7=Y)unrSI_5EEJkq1NgaefIf6VQzbV++`TPX0InV2*5 z6`gyWh-J0rbb6^Sef*(<0ebIAdsYB8xrCre@gX(*9Dw25+o*P5A?8|5puk1C_{#8W z-@avJuRj)*S3ShB$8+g-m<=sjwuWq)ji43l2fWgu`gAuKefmZ9JfB_vQvu1cKUi4fR$+BZpD#(#S^c6QMN&if$wMMA%Nk{yr?Q{5H%#R zymUb*mR<58-{R+VueQl0&_xSz2Zv&dx)+oqGBNOC4B99UMurb)7|*ZER&b_Z`92!R zIN#{w_k^R`yQ5ZKKu&(a_aV5p8KrG`;LF z_11Dl&hd17Y!1L8)2rm!Z!&famc?850eBo-NxwOZUpwfbsO&O`y1ny9;LhJP%fCq+ zajBws?mhTAWg>mkeeT00b57isW?hIzhs8A7GeHZRGIG%+j!@LIJM1&PG1AioDkgfk zdSV$V&sN04;0!8y5-V1BSwrLYO5^qEey~x~L7z5H=0|WZ-RTVlZFxuzDOGgv;$WI* zzMC?BL_%uITruQHEk#b1!OUaQP@Y#Rd9^nKBZq2Wb63U-Zw!IatQ5Q~$wGhkUa;5~ z0JWnQG=yd7dJi2j%pn1@bo*0lRWH~Fj7Jg5gwHU}cjR|+|%mRPr<8})Zo7j83q z(I59sl8oEh!qD0lR=ih`zEcEg&6V``_%hNrcu5}u!|Ak^JfxO6;*Fdw8Unl}TQyuz znL3^JHlC%EHG?J7Ow93ADFB}vda_g|8`T|;sCS8lV;OwIa4-!fb2JL2%hKo9nf zJ_xxr8m_VPgEsk%qQJNrw0`3_I(~*bFQK})X!@I!a`{;^X%ZeQ2&j7+ z!(h%saz3I+rWRc>_s3L3mOP|x31yVFz#OAfnbp@8guFhQG_^RL_m6>`ZKl3l&s#4L)WDF6vh(b-d4R)Vlkeo zxudWw^Ci`GDj@&OH4%TV0GUTX3nv9pnA1|4t=xrzit?b?w*XDmn`q$AKB(&Mf{M{o z@$x?NoWAU!M~U_*x)_D-sV5{~6tys8wF@--7Es5jbiS+DVd_JD$jmdPNY`TV+IuKg zTpNrN(q1ZV0spP0q7RJ9;huzIMYOCb_c%v&8S4GpIt|L))VzR6HPNaq2%vr7*hV;Ha7RTpz>f>3VV zK}v~))!!qb(Q1r3H8cFE|L0wMHTyd^ROQmrLl=bM%uy7qT1K1xPNs2*ETTTe>Km>d8DdQ9S>}oP>gK%9@miQ;ZR}G34CJy$rNBMxk%E zmZ+_LLc6;J!ugXM-?zrVt$Qkcm)sT8I=$)hvnY6Z2jHg6E^%c;ARb-IgvEo0r1_*= z7`!p2Tb|iCe266yL%LEm^H^k4>?pIl55o0}@W9CqCtY0OykQcWyE@ak3L9KEzbq2= zWy9EQHOVUUMsm#zQb?SL5gu#B;L~%2OsNFM;lrT3*M#hO=R386JC;RVT{f?1qScLl zEOcUqq~bQo-wDj>aN9^bQq;*|Vj2{)FG~i88DQ_@PM1c0&gLAErZ?F(@EqrgXA4I_ z){vQESGyx))mUn`=3esQW5O>c6Lg2=T!(eVd~0)j=yb*N#M3k{r-|+*NK?v3ZD1eo z)m}TG=xG9c`MKY6Xf}CthG1_CbCq7c5C^1L1YX|*LA)c~wZsk0>-n5kKN9sS>S(#) zi@1v{)9T|ZIqo--wtxCeXKwDJ^V4Ff_Qxx6i-j^dLsBv3oio-Z#|Wdy{#fJ2Y&Mf4 z^g{j-t=U#jt&iKpg2*8#_GuITYyXJ7siBy8_pId9)^wUQT@!nC{czxWhoq%zKkVY4 zwdJxD+`eQ{Da(mGJO^R@;Lr43{VesJQbuEwH_(qFo(FVqA~i%4KaDBG&~x6GKVY=mIDf143xp0QBa33tg4 zMjIRu|1|@rGEH#CI}QnH|B2l_eBdvyhy1YrsKdq%iOgcZmr_V>RwJ=u{&&gg>IgbI z!2q+*WI|!LGRrIO)5Mg$lDeASbV{<6+MIbm!(woy{&8?D55`H)8nWTMdr+h$&+K{b z7gi+3sdmA51VT2Y1;r!Ln<;5WlaSFyya{33Tv>+|6;fte1gdm|_^3HoO^_rKN# zAAMg4JL^qCM@|WWH)}+5h6FaZ5-ENVOZ{3u(1dr)C9c0jAH(<@oIDMef?i5QZ~uqi)I^f*?T@I&7Db2>#U&{_mU>PI75zw%rNW~h{ah05iT{3`s!VwVUq)~ZudG` zo2Ch!#%$zhJF<9(g|>AT^x{MmRzypLhm9u{4WEj$b4H?9cN09>)=YVRKWN+9;}l49 zNq4_4J9vX?vOD$3;jF-e*Mli$ z$yMe|_Q#J4ed&^}4X*T^NK)gR(Gd8B&QFj9cwfIY&PY`Bn221}0o1FvA@1)Q3mx9^ zFXA)Ym7*{-+>2qhU^iqir?<%^V zr`h-8@QTVp;ODhutW_fHcNozd*$XsNr2rvHkyv$sJ2EX2n3Q&*OM%MJAqnkPZ<9p) zxJZYjwQ%9DBc1fJz)u!e7hk?CG#Zu&`Qc;mPpua=Bo2Vt$-nf95%-EuHd4j&5)t@r zBUOJ|Pun#U@MF?H3P>A_srk%pepF9x(*v>Kl{%?3=ZSzW<8XarAlBCVLJs6orSo8%o)yd;pnh=S+}-uX zF|a+5f+02$wEWCp@pxt^WUfzu?5wBa_ibsq_N9PwzeM5uk$Kdxc?1<4H-S{YL6mUN z2su_sH0JgmQ9efp9lMT_aPCHDjsbC-@-Y5*G}7`%(2FSE<2cMAIhM)D*{%`Q4wiIg zd4G~T+bY(>n$`@SDh3xws4Q~?rj{A8?34TJ0h#E1XSc|=n})z=85qs8)g9Z?u<%DK z1*$EiYtG?#uknhq4#eT;sULLggd69`#$dwhU=$mt;trpU&h9Cv7iw2XW2vdQ$8x+E zpVQ&K*qC}!D=w9V}a)$7?v+HOfJc?aIVxQRTYdeVb$ zidY#KhZ$84eD|6wQl`|9{pfzoZVtw#5=Wu1-vuQr+UeD5&OzN93S|dr=zGr;Y1~=b z$-L-TUh!Q%G6iF{e7gJIkMm}^aPDD`&eS{{G(Jf!GF>3MyOP>+Ci0x!9@>fB zMH=TF%Z+{McX=9?eU*l0wJEme4TH+Ou5`1AYqn`CscdF9EIrCS+MQ-tzfzwlV=aA` zFTmnM&7@`Xj-q$l_xNcI%T(z&Hqb@@W78^2$M;l4Q z!Vo`mHa&l@jYYDR6m%*GD;rsCS@4QvPsQMg98glK09lhPG=-<)NxyIOj~NG50|Jmz zrGh?FEsGuv^Abrqk`Z0Nd+<#s>CQq0GGO-d z-A_yCSY)-B^zsvR-CT(4%}Fr4_>V?6R?ypuKO}u11{SJvN=`=PK19-LZXxCHC$OC7azgXdG7|rcdxjgC5V_^_l1TI349FksMEvM*5QhH2=B@ zF8ybLO+zch=!bV`i2G+sx%HOf;!cucsU{q+X`<^VfwkOa(ivM$J^M`-tlTs~+`8F+k{HWzk}|hU}eo z)0r{{^voJVk5ED9?D+*?2Xsh9*v9P0l=l>F$GY>fuEy-04kiJ#LX6 z3+Ya(@|=5jce=K2ICm1KV7JO7IGi4XVUMngteas--C>B0hBoB?)15XLX`_4M1xeah zPn>+GfF676s7<#A-V|;i8_$O{%fSgN`i-U~^?;|xXgIPkHmc8XnAR?(hC79{+4w2l zFzAVda~WhC#N0$TBlI1%NwhenVmk8;Tr`SMJiQBaC6+9U_Ca+|Hwu3Eh77wtp^wv* zQTq224SK4Cqjx`(#bhsR&fYELX5Xc%Bn_O~a)C^nLy?u*6HOKdm|uO0X62h8|LuB8 z8*7CD$>vnqkVZM`g=8M51MBjq;u-I)*KxM*!|yiAF3zKuZSiDpTTI?%o>=R?g~qh$ zp-U;Da={jA8Dvadb*8}UUN2f&^oDGCKbP<}gOFhW)5@cCp{FuJ9Rgv!Rhba+mUdQ* z=JV=*^qlu0`B!(5{;?SRDhWYH`U)D@?1OLHUGZvZsYs7lDzt0P&=xfoiRq4_frsai zYPB6|wUWt5wKtX?V$ogvLGpXSeRAtt!>XJz6XoJ0bz0OYTsY z`7$K8HUWP*N9Q#4D&=0fLV;J^NsBv{3EbuS%Kq(^8M;sHUfF?`s4aZ>cw~Ab(MhQdTAuBmO(Ky{wI44LA{MU zW1&C5&CjX5}5pcZ_6$9W2kBjQq1Z(UVq&HmdapS_#zj3~yI%!I68F0!hy zO4F042Ij+Dz5B@J+3rwy{Ob`T04IE-kiAR|_pJQz>g*%>LK|qUshwEycO1TOp7Tgm0EJ1|^F7;{OhZPAJ)HA1 z&s{Ahr#N86wsmANfU`TRSVCT9fm+Kv=-4t_Y`;C-*Dd53jy4vY7>T@%-gp%nfmO^` zd=Z(zox^gPS8q>d`48D2A&0CtPleCr2(oWdg7E|k?7e+hD8_}NWZ+>M!q5NSt+PpM z755+cGoF{sUY@Q$NhWI;O>7>C|95-wR0Vrh?-ea$G;y>x4MS&MrbAQgsoptG%w{fl zsk$j;dTpW76|Q8FA;Y; zhX|;=aKfd8FZ3Wf4xiU)isk3|f2!<5QSFP!eVwV~;uR8sjw3M2oW;KD_28P@RjeET zQ#{*j4aJ_9#iT4HERNJfd>3QMAh(m^SFs;Hmr2ozp<^kz$)2U;Jm+3?h+hAxpr)CP zv`;}_%vYC!w#QA%EBHnF%t?FxgLjx+PEZ0%wVU>5;oG%BtSg#GPq!(fhmAWu{5pZ= z4|S*J(>G~@I70r+rEj+j#f_>d*jti<2FFz7RaoGb*=&-YwutmNr>mZ%BN{SlXtz=e z9f>NTw6zZ@Xr3WXCs^Y0UO#+%yq1DSu#}m*jGYxMp`PAOcCnwuc;?bH?9k$jPb4fI zx6$TT`KVlx2Dt`JdZKB7qW)^AI>mW5zdk7K#{DiQbzE%kkH`M6g#M6BA>HQ9_XZs# zm3@+I@n1>zAN?ccE2GKKYzI}2j78`BTvQ$KLB`rpoJ{9D%?b7=$$8UN*#vqU(n_O8 zO2OLnn+V%588$H{h?vzz9$I%KnlqNrBoV$@gqdX-g&M(Z3-jJCpd^)iW0moYTwV-S`(Mbp-8%usfi2Km)IW7!&r zrP7Twu<)SRxmyX}{%GRAuIlKXzCv8DT`mlU^?~;`dE7f1?9_WmDBU)-g@j5 zyxxjXcyXHUw*`t3H$sK?aPAG02d&$fivKKe1SV!L${S}kd&xxN1r#JrEXdZZ-x-Q*7HBUEDw%J@! zdOr>~Q(3KeEEi|KJK*mXTV%^!BNa2|A8b2829MrRJn!zVZHT406>(S?5R091<|y3N z7xk9XsA*1wmt;B_&-KB3{rw^(m3wQ;$3siz1a&cHRzi2~Il9`=up%Amx@{hn)R~Ls z0h8fx!i)`!*=)pFY zv##!fslN>2X7o?QsxP5wQ|#!q%?w)N*GdId_M8ta!U|bwdfQ75l{55c`-_E?*3KRK zBhtuj?w|p)nctfAOk~^}1QmWxZkub1kXIwos-Zz0J}kxNd_3N8_9Xtj#AV|xT6s7Z zCU(8J8>I>L#SW+l;hxscX*9kmi^diD!&*&+zCSof4{Tz{=PvX3jrUQqx`jk(>}e{L zETdB941E4QO-MZViBTRyVY2Wbbt&>=ZCpJ5eOH2?M-Q@1$Yn;89*P^7f%YU#gz>$y zjJ*wo!l?1hUTWl=&Vh}*513(tTYn-c?vx6~yLP3GyysuBX9*>K zydy@>k`XqXQ|aHsfbQn@!cvWiD4ITno*7tU;QdHg>E9rwI8C~EYmaCRO~#AW%CLUb z7yB}cFm3){p|f@m{daaaHOv6558 z02#HOw4}rdy3^Uq5G_T^x2qx5ED@Ko#?r7w%1D!&fPl(8ym@(%?#~FsIm=dw@0Ay{ zvv<8P`)P)U+^Iazv+dWW*=Si*PQms?^!83aeA!S!am-=aecu)v<(252#~IPCvR!De zzCv9tu>WOu1#KNZj5eh-Q}n7NB*tZ7VX-qlHpF0H2hXyj!m-DzJEe3VLsDZ>(P{jG zn#(gWy8OGOaz_aM@SY-agB0{`o)-srXLhCVr?6q}*HV&Vo_-*mShbCGie69@0xE_HUyX%V*M6d2M*UJ0kkK9hUrj;)gL-IuJL9QvBSH zqPVJ#ULM#dHuH|&pn^LX!^dO5=c_cwdL^0oE7IbBiWoRT4!6h!i>nP#Khgnp^BghA z+?xLRL<^mgk^H;oAm@G-ed_NE#}zB+Q*J*Ry4-=LU1cBVe!`vRI9y)UAH9x6(ttxz zsC#rooVqg^Nr(Bn_dSvBT#Lc0TmA9=Qy^l80|)i=`I%aX@?0gD?&ym|X4wx2dM#Pd z`#c%hvYTyh4-C3#3jMMOsvlNP3n!`x%}>#gZ?wm%&nGBvpFZ?HjHjyGMxu_h&ygP8 z$>!K!x)2*gPneYcl{{QdB*)VzW{>$^W1L)&Horc^tm0`(p8YPe=!O0t(e4oB6r2M|)A-19SL%VaKUMD~&w*FF@JJKJ2a*ol_WgT>W$~lTle@8FmmP#Jy&Y?x@2YLT&COx+u zAzA*VlPX!t?LFbC@Utl;w}*)^Z5c}zV}fb0ZUC+yHOJ-u_KT7Wwak=#D9k5B!|Fyi zj8%-si&ysOQ0vN?O=psiNWhG-I#?NGf+O?w#l+(?MGns`g2%~APIHgD{{c7rQM^IH zVk+v|ZBcq^AiJ1Ya_+o`{wztumbkrSxPdt@dF7;rY{bkjqc(k6td2e>dgs|=yG0^q z^tmjVVxNTJS>cG{yK!+U->G|~&^LZAD92f2s#G!k{Aj?Q%~9}w&3FB$Q&4ey5%sCt zPK}!`2!kmSy20EI&&}bIQE{wbZYY4f{UF@cN|F@wF87UPBUx$;$LL$-6t-6rYB^dk zDZ539qioT26!$tNFQWF}$7z_HK%d!1$!+)qd@`yO`zo~H(cGJJ_2cpU$sgemzn+Ri zIS-j{j|+dSaOq|h$$32#!aNgQSML@(hTGAB5)&l!bEmA8s?b!>gf}w?@2fSD+^2t{ z_0MdZpy(j_wle{Sz=FXcY9e9N}Jtw?y$< zI~_3CNKaSCqm=!q52%AqFav7)GCw4n>Y)5{0mUs+1a)ym3*QxzBUh2-5E(4<429z8 zeJ(m#(~zl{Mz?(OX&3L)O9K^f^v-X}a&4qtG8Tw>7Yf&!*Hu87~SkAV8qEOh~*r?k!PG`KRTPXY<0!*-{oXn zAAy2iy=cJ$KkQjH8vpew;Lf!-Hp?=9`bIVN)a;}`XL1M!H1W*!|NFtk6gN?Y-l-&F zy;L@=_gO&VH$+@K>xhDeq1dSNNLL#98?&Vf-W+2Ja$~&Ue&x zdPsXE*ve>(t-veG} zDQ}%TQuqvAyO29SeiAIIA3}!;wK28$BhC0g*xk08Ug-3Lb$2ydB*R^+#5Pe9WrfpU zhv4v_Vp^xa(8Xmdu=kH6s!yt7vTh-zl#in$!C^4DIE(HvFW&F+dpe({gnPBtIGN*( zfS@pJ$@@a76Me8pZY?eP?*(0t6Lj*SF60LEp#<*?b}q4FitmKs``ZWK(ry(9B; znRGEd3S%=L(1DntSX6PG9(6F=&2SW?Uiu)ByB~Td>=D~*CMBOaPT#4TdhqN^wm|{b zQp?od%wUlPpD7@F%%fzE45HQbptSHBAdDwVu8m?X%hTW3) zk}rn0#i=?ka>?zAnUfVz=<}33f0>djcfyysOQYq?AG%+gf&qp8v}|Gkx+Ul0%G@*5 zsjmsUlV!}u%*2jFRSJwXgSxCX=khLzKfYtQhhmP6F;8js#JluZ$q*Mb!s*CpXLy^9 z!o#~Ik|E5yyH~~>t1sPw=}}nqTuD4t@WR&C3lg6sJ!(A3x%%|2w6Buc#CK$I+g%s$ zr>pd=lPp#yXzC(UZMkw4qlKP5L>as!+b@oyC9eRN-J{wLe%(_8;AG<16>R@n%iC9<}0VO#V z_&)N%9q(&&yoU*bBV^%p(81-^3Fa)MFqco=5}&$W6SmxipSIo+dbM|{@v0O0d>e-6 zc}c>oZY|B^-i7oT73@82Mh$k+$d~CO>a2{R)+G{)&TERCUO})ji^6bbNQ8xPKi{+v z?aWs+*c6HWd*#`&S}ZJPexsj9YcGG|=q`dF%=o&-?a+XUQH0riCK#!w-^K z8G^uUcW69m7On3+vCdtazU#lH@{cL-__09`YDY&dW0N3ISbM*53HCZ>Uif;Z@H74F7SRm zdj?HUsv=2gHh#&Eg57y7ScS0@a@|6*jtHiCqpRuZ&AXDBUzCLL6jxHaexJH*JtPiV zNoeLb_Tbe#VBgJ7F?*c_Ci35T{f4i6CzQw0cfrJ|HdxK866q(8(@f4{@A>Ww=O)fU zM5t4GY8V#PO~Jf1*;o}T5AV)mYL$*daQB|{RDTb7P2Wspzef0T-}$wP9L*^$M90Ss zqRmtZ|GfqEIwH@WxgAvWekgrd=7rz>%zrju4-os!3+6ti4V^Ivvbjn7jhK_Ex{cIh zR?v%&+%Ioz7IO~iBKsbIw!8rBG~0$YT!VE;R1wyBY%h#^<3cX& z(R^2T=bpB}ns_JiR{spCO%D8g|)gRCHa6jiT=h}{p#op>Wl1-KoIM7+Z+}ju|(DcNz z2JY}W9Takle~OE*hmeQNTq>Pui?!Ypacq<~-^K%js4pGvhGc>us6wQmZ=if~l>ciMmcYG3#8~mmk zw{ZBxT@+H$XK7WVJ*}BG0iJDEIQ2aNr!RjY(*QM57LkRetMAhv^Lyg!8t%+{lu3qq z8IhOTJ-VFlNV8{+g4{PBcnl52#~r>1ZrVdp56ti?mw8Usc2NGCMhXrKXjkog+T1*y zcC%|`+dW0xzR6CngPJr`p$87=X;N->2tJ&NMCQGnboE9uewM^Rp~pLka%M7$IA{HG zR2Mw|ypJ9)?av*`bu`%72#XDuit)^p>%lYN+iBg%?S3{q)za{2t_S=l}g zl`Ego@p4zl*Hn_4aVr_7WnqKw53!S(`w7Y)XsLM|U2loRq>J-t_Sgt&d9Z=^&y#Sh zK@XX3zVQ1`70&!#lAf4{m4(YGVHmTuV%baE7J$3I^k|M=55(7B5mCRKaiQ;Jx~c1h zLw{4zKE{q7{%RquE-@%(mUG^r6C@qWd4+lEXshjqt-Z1_N!tnD{CB^#^c@AUZ(!Z% zIaF{}isvxH(YvHt^c`hN+7p@KeIpPPUb$iJUFP3&KXGF5DhktEOlMC9P&u>vyE;t7 zo7X*&eUxX(KGU#urUf3_jz(Ef6classCtYdMOe+JG~ZKnkb8aRkyWChX(>O?hahIG z3w^rT7X!Bqz#_+ByzAh(di`6vHz z=i4VLmDi?0b3RbuKWQrX*n@*m22?Axni^X84%NCw9Bj|Rwad@A7s5HP6B{IJe;lRu za(2+|>y1CE70jz#&(FIC@>v!|d!FfuW%rNJ^e-;B`9lpVy&Q0^SPBQ3UtF41z?q%F zn7={|H-62Ql#li%yF-O=IyMmzaY7WiAEpzRvgpDT2gq-pLc8A@VwxV|bbvKJzW+;( zCsQ!yfg}5Wz0t_Mk=Wd7%3tqKCF3G6cMG#QtdtN|YKP8?Ep*X23iVNwQBXP#|CG2R zD9T9b!+nYh*udW*zDJH)B6cbpBcLpoTun3Zg7Xnda-P`!BNDrMve(ouf%`Byxc~mR z7(cdJ1o}772di3=j8;IXr5bedTFApJ4F7pX!sJ;I${Lo^)I)Y+^bZ;6e%Va%F^_2T zNe`rk*&-(=4^GlIKhg$>LD*L29MrBzv+ut@tEE^2`@~lUPGX^}>Xv5h(AH zEG~x*CeIsYcvqf>WopdhxDt<+8Gf{OjQLl+`kNR~fcZpH4YY=(<$ZEcm_riJYt;Gk1r2>WN7Si( zp=V?Nqg&gJk=2*y2?|zls&L03&vaC#Gvmr2lZNp}`E05lcBZc+bDd5yn9_~c8-dW) z+#!iLypqhWYeOc1Gj_95(N8@U4SwzPv!4<|`etL>0t-CtolEJv)XB7G4%F8wVHtPV zvpZ68wY@u)zu73(*_e}8`%y~2YK!2P#ZpC^)+xi5BHfQ1W)7K(FB8T$02J+Xape^B3 zacS8^ROI`Ey!O%6s=hR$@(T^0e}w8E$?;4wklCdBXbQjEEz4qX|C%a#J*bt0FVceN zE#{xzNJZ==W8|A1r8T#h(Y!Gahwbzbcv=Y$pE}~8Zx4L7vcOI~8#td`L=hdMDdO2; z`u*iCDJT@ewpUL`|01e1@n$Z=35leVofA{W;m=lg=w&^iH%FM`X=6pY>zJF>!LGQs zgXsR6*+Q}XpD2D7gv|U%L@^Je$HldDrH?dn;xf_K<2yyT7SpwlO*F%Tdm1$EaJ969^!*XkdEhyzANWPOJSQ}m<3^SFz@V`G%pm_t*Y<{DN7YvHTNZ~_ z{e3j!Mn7o(iGup)p5lzGGUQdK(C6#Jk>0nHcAH3%y!Lkb`78}b`whqVUW;jXhA)QH zdU59btuP*Ijhw&IboeZvkNh|*J7*H@eY;SclIccD^F6R~VJH^vm_*9Q&(RR>oL#vo zg(+RTBQvQGOJ%Q!L0<;LwkeI@-MVxzaih?*m7}%NvQ!i_5>E31a3M;YJ}GIlYw#cG zevX2VRygdnA$;kkICbqTMT@Jnd-+6KH1ao{_E*9$vuW_od`7!7uG7ZNQIKv5V-|W2 z_Kz{gz+@$ye3*x@J|Sc^`v4uO{zhqA|I$6(E2Q5QwDj6lNppAR$WG3oylZ_W2gwvY zQ`3>L^#|z(jK#AZU62^Ll1lG8(cG%nv|Q;2Mb|GD!pIR#i@RX`=6{s+(Fa9^k7$@l z9ZmXgF!JkuQw6&q<~>!Fj8`0pA)j^Vw8>4E@V(5@=exwKrONEMDnQqtBjH-lp2&X2 zC<&N~8y?EgU7|vJcB#;j^+S+d6N-sj73e6xLoWnYOGfd%aNNrN7`bf`*+%oK#s44O zp>nb8Bllr``(RGwAXw#w!J9kacAV*}$zCsMKkNiY#YEI+b#R9)39<4`Vv}wce7gHv zQoPC?GpmN7-7g1bOSvbznOQMe18_e$kTw_efLlE~<&5G{l4^+BQ`eb$)0>_J2UC43 zpZSm6q1fSbBvVUOMRRaZM1J^9*A98(+OAP}BXv(ax}%7h-1i$;W`#hWBR)3_!u;k~ z^yN&V^f&(5GIvu^lRq4uRgw&6)byBL@p$KUY8#YH+l!JRwY^iab}2itT3?8?C+X0+ ze2qlUB^179JQQWSL;77bHQsSYKlVy=%zGgDdR`aO2B#>!e+Cu)kzl3VFRJd0LNI5P zoVHw{+Z*@}=jH^BZW?%L-VK%0y2D&Q1a^ndP(WxUefMWRF>^mPu4coX{c4`^-SPK; z4fV)Tq?7VJP`^5wqTZ(Cpr#%Ax$dF;+98#ZSYole%cAmAFoiRO*b^w$MbhypZm6# zXkH`p^lfhvTyr4BF4LiAHDVQl`EJ`JD8?FBDx^5;lSViDhampkadD}u3EH|3qJnFN zbWx`}Ue+{_wmD&i%qW`Vc2F#3K1JW({@C}%6CnNbmg~%{DEB>5c zPl-m;MQx4?>iuU>Ww!*Ja4Q#Qj~SqE))NZ#SVx_g**~D+ObJOvi0;X}M*}ZhXc-2l z(duRsL4thi@z4?5byPCWoX5gm=cXf6d z<3oWAl+G}7%W4yiQ|-=KXzu^BNA1sZ9X#pgMOPAZG0A@l!v8AcUr{M}+O|_KZ)+?( zlYzdaA1Gbpg_x0Kg)e>9(c(SxsOhsB=GU~-(sRLBwY`C!75Gr2*<11}nMavf4=Hk= z6C6gS;dM7BksUrsvEqR0z9j}g|BOKD;-lK<^y_F3jM`=dP?W@+*FaRoh_X91~)#+du3h0MeJX{zgP+TmmhD>*wnb=Jab zr{S2;dRnxFIpHbN;q;#KEEY$}c9S-_>}?TVyL!_T-A0MhS(Vqh9@LI()f+tkGb1_}NvV|7sO`?zQ&WH~Yk3@|@Djhf<4*kW3prdZ+ z&#afHLyKs23xChPaGv)WJCKj3lFF!IB9r%|15YZ${DB2#W z=-1RqQ1Equ#id%(Wwtp>HAT||Yb1)jv{Neq$_pJ)*O&X`MTN}z-7J2~^oQhF7fhIw zf{_%CE0_wCvoSHVHi3|P$XtuD;4 zzxkJZil_3=K8ReZD@dh&3j2?2$z*~WLJaC@$>s%A-A@G>|1vQ7kOIlHOhESEKy0KV*%cAd4__OH}lf$9h|8vLM!EWe`9zhWWQP5JlPuc$z>G!V3VnT-uY-V<+ z@!a(}J839>GXrl^A60ba&)ml^CA2eMA1~JYkD~LA>v?^{c%{fJNof!zk)|Zo_qnbT zEg}ukl2y?_q@rQV-g}Qj$j;t7GP3vHtL!~~_wRq_bvh@X&*ypW`?}um9@63aftDGa zd4H`ZTRtXqwyjc?A-~W=X0YEUY}K?$S_u7`o*XJ!@{jF$GS_fCRMu3@G5_k^)-x7E z{Ewq;a8>3k(Xf5-D)q+N7a#I(qi?(m^~+*-KBhC@jV{5#d+qQ_GFhF?HfvnP^Lb&H zWZJ%cLaz-u$SatD?zM|BX;yE(mF|9@fPLPJ2k*exv#n^p_o#QT_Tn!}-;FfiD;Rfb z0tOr2#Ga+n)7RDTlKdI3qz>YobY$=vTbcL7@?}{=R$Gz4gFliH-D!|8&2qT^SRCj3 z&4%GQQ)Q=d;$$mJ#w}^WGM_r!bgVbev~^_q(_8ZYs|Dv>j1|^#SN>a(?B!8DoNg04 zDWAgkIMB(MUhX~Ewz>(T=BBH;9p+&F1#NEqk;ioNY$#{oA_?g#qTa= z$xV*i!i z&|XrP!?j|W(LMqTP7S4H`D*+;_FFZqe^MRHj#N`athi)ACDfqhm?qAHP12odw9S$( zqq@@ew9H+XD)#x<5Usj=Mx8}nIQ&Eb_s#8xFK=6;?m0a*vSc|H9c#&;mDsWQrYZmfV}mb-mc8YDdoB)<8N)Tk!IP8MQ-G)or=g>D+Qe+Ii{0SyaN*#gc|b zc1SWliog$FVBmTc+p|_zy@qZ$KWZ1GnR`8ux8gu;8^DTN<|SxrX3rn~^HGsmz^`pg_}=%EIzOy6cbAo7>+N#CeVIQ+hj_}T5nQF#eL0lM^yZm25X2&+Cp!#!)uF{o)YFK_#U zQ99Gn$*C%*wAhamlAC>>P=#Yw1i-PhfG%|`IK95FbUb5Z#%@ZVwL4JxJ%**?R&Q=| zMj09J!mzjg{MxHJvm%R7+%5r+oFBlpiZEHEAGSu`|25ZWv7N!b?^66xHLEC0qKhU`!r4Cw8NI8`Ui1yE&08S??AT(Irx%SjD%xD zB-g3Id3W)k8!tq|InA*kOwp)C1U>T;RQ=8W!SX>4WOa)L-&&&Aw9z=J{~H_Tx+3^d zJSR1sq57Gh!|>>XShTka#{V}L4q9Es-L(a6#`om`+cy~4bg%GnMj@i)H|!heqm`Qj zSB>0=PazFycD{;a#SUO^Y8*ag+j3#w7kD?T95a(G@!fx|=F1St$;>sT+jH?^Pu{2M z_jrtX?EM1y)nBJ~PP3h}`wU^BBXSnp`R2M$f zdZ(H_&Oz;kb<~h!@tnHQ5c;PR*f=kdHGd0x^3{CoIoX%(FW7O;30F+4$m7QCGM{Mg zh7aAX;Gb*<<9WIq;Q37@6qwR;*ijrAE^cMrp=zY1t>&>yD8r`SL4b}vCJh`y)&dQ7 z&Qf_K;N zkPbRE1N&d-aozR>>iXmV@ZJ3&N=!~6?;s$pDbFZ1CtD_-;vj!VaM8s9mi zrmvX=osH`-yJ{6a++%_{u{F4KhZS3zTdSg@ZBX877tT!>NWJ{#JmKid$^E;sS?&yM z*pS7x&qIWLIs>mwR*N@n0#0@7A>MW!ICQE^(baKQzbTsN89k3Z0qNfwPCn$Xy?D_7QE z3)9$Js;_jLA9W=AO2J}b5o5i>UixiS}hpP!}7b(9q7-#osGml zc^gySTk^n%Y!+_bjvB&GFtE4|zn&|w^UoMKU#~!5?Yh*{4Py9bEq-gYTdkBC#-O}p zz8h=Ao>vZ{@ys^p-)p+6Fmx3*oCjO1uwi#~2HnjjLx0*p7Ipp)4Szkv-ydPZshNwV z+lO$hZ6-@4ucF(lF0<}Fz~~Q_!o`f@qN9J6OKJ)%8!p1@`w#FVIg{-t1>%)QTP`*1 zz$d4L|9ht@vNtzk+~_V`oR@%sH?!1J;nOrdH3b3fi*dlK4eM^5hm@;Bv861G6YS<8 z<6>LM5IHjN$S3Uhm5#K+YVweq@?M#X_!Bl`Y?C%HbbN!IUgFsOR*tzb1fjN4(i?M1gjZ^aMatPYEJ3}NbY`dwUw$xTstK8^W#O~ zYFI6_qPH+Y4z$S^zvTn(v=8;!sQ)^o$7$1Y$TrMqy&5+{{Aj)2i+y~2sDC7miP~w5 zzix^DL-)V!3Szl?b&*q+vgwS@Dc^KJz`^l3u3{pIi$U+?((BXMVFo+^2B zNzLo@OtKW0U^G7w?-nPs@fc4wuJr?T)?7hB+)#1k_2r%0zVsVZ6UV;Z76;vJjG5+* zZo==h{n?Y%tv&fe&ZO^;cjTwLV_|zXoXw|+r&P|}kH%#&sm&k!v#Q3DwZi6HlEDQg z$y}DW8t&~|qjPO>u@%R1rBMVc?q|p@!-=o%97QwvGwnO(pm_Z#_=Y}0{=rTh+r1BK z&S=0Hm-PAKTRqG-Fp~3cU#@So6usMNW3sh)&o5S?&&F5iEa#2KHM(M-oP{dHNp$b` zQ9Nzi(YtwIGN%1C<(ZT)R;3q1Hd%AY%ZJ`;uJk~$X($Fp4x`cebWS*BEE((}IIHTj zMl%zH4Nazv-*Juifl7GG9%=GGZ$3}Ag#XNExc}A>=Rd_W;YD4T-|Ni{ztiwBN7xM7 zA^dD-E53nOn7z(M=4@5znj+nnPMK`JW}xEzBJtFI)4aH)#j?|V`7x>%^>r8ZHBl$LfJF08cu8yx5$`EHFCmSXxX=BLl0Mc-}ONa*fRyMm$~7MFtSq& z3s4eb#z8)*JmcAdzsqg;Jij%AGDa|RtRC-f_=Hu*hVewVC|>-t4nY$Vxlx!Kb$rL5 zcE&(e)~oT) zLtq&48`~rG*|(b`gG${oV%<~tG+Kg?%fGO7_7*%h7fwOr&MX<(m#sgH(F8y7=JbSW zJQna$RWmC?v{5iiuh*7y@p?pD4ntnZdi>oOhadYQP=DZE zZyrbc@5hJ#jOky{1jc$A{?Q+f0rf6xHeT<-WuYnDZ|}p&nzpP_)LvM(gSpLiCITFX za`sGdXngL^qeT;Ox|c39{|(?`KXF3{&$MW9YwoN%gyt)%px5qjzH0Fl#ht$3W9miR zmYu>lIp0>~)`afLmdu`GD!oKsE|K%?iHU9K{>n>w%{d%B(oN2T-h3oZ;jn;uROw^Y zN!#VB{p(&_vgtlT$2gLE9HIP=-ly7U{l z0)DjpMF?EY2TfTU!3}EN{JJAp@x3AM<#gocOKs`cUb3#@n+BarwS8+r^)R^UP3szK+JXLxVKqy~iV} zqc%1twB&^03(>B%J6l{EMt_H~@M}E|x5NF}DqxO!@n$HuHIV<7(BsH$(FYa6K5evm zFl@X3g3YIH!Y6)8n2k$-UUvL{nem{VM&O_)>=e%ZF_Y#%fJddU0g+rH{!0=tIIca8pUfZCnPRnd)PuuRy znwP<-X5Y|nRUEsOELN|?&r>izjN5NrQz74?SoQ4zjQSbJ>bU^Ue z0}qBZ=BdeE_`1jhHZsG`I8le`Uxn#>$d>`ln_=79OE~l1na5L>s2#b_FkkiNp4*#n zd*dHeOgoIPMq6-cY(LKU(3699_P~l4!bR6h;`rcxEtZmKp~*ZI~EUAN7XnvFK+lj&d0dpJ5&hT((xNET~USD|0o~e+WEGy){G6i3{UL zbBv!Yvj)dGYRajuSlw(X^xBj{d#nyaS9gZ_5M6HlBC{0PV|=^Yklw;W=-bhT9r~Vx z%Vjf_`d#jfj|Q;&e;?J(o?+a_0o?L(As$xqN82rJnD-}y`PWiVC^Ih(Z3?sX zgp+>d_z_qK7fz?CvR$^E=RO;qihry5<>Fw=%)%Xu;cU{}83Uvv^2Dhj8+IGO10J){ z&@`S0SHHv4cWcq&)DCob=7K%at2ri}nw^sASSy?un{S_0x%j4TMYQ1A;w><{s4E=~ zN(X+8?0TE4+B-FTR9v4&B2VB(W*bJiR$-46D{dXF#dmE#AU~-)E{r$ixn?c7J$SIP z8MZ-Ht7*o&vx@QGxgy+h_yU@DQj%TZ{VJO@2NSx8=P{P|el+0x%pyG8){$M`eMUiJ zc@G#r$61?bHV!(4eao8AXH8S#j=scy&Ldd7KbePjwC7FlI{euzf$0h2Eb#S}9Pe!u zKe150(UPyo?|>1Xx8SP964Wdm#DrUtdA*U%Ri})xu+)HAlKuMVW<$$sHuM^J7G=F- zSyJaPes?#)qL8+n8uSur^9p!>j1zN>H)H!51BMQ~iPf*NX}oS5V&#l)J0pxeZZ+l{ z$;`QX2C>b&?`md;HQ1MyO6}=uRcMPZ=)SWmEgmFt%$0b2?d2vtKQCSn=)>)4{n2IO zcD&Z^&Wk5o@aI|s)%bi9xE$}Ek(D*GxFsTwWA0X{ht*}Kam|jky9MCs ztR*TtV>6O>@5EP`K?g0q0>^$OD1MO5kmi1T(|jKOn?4HX$Gy=wJbb8HzdEI6K3aw- zeP61Eam?$QjCC=l938g>*N;jD;+r-rV!P3{ZX}0h_)3rP7EYD?P!~*->0f`Zvanf$ z9)ljC>XPniZ9xEfwAV(9PoHu5)mvoxTXLUiiDVP@Afo$kOfQ}etBDP;=u>Z6hS$<; zdE?G`1vwnNX#>LFMDtszH_bzeF*~Lfn?H~a^mI?|m6^{(xz|67e+i@Y_c3HbYYf-3 z=Comlp_|;3hyN_X^f!{F>n(iPKT#Ol{g;{>oq+LLQQYqO7avL->Dp=-YHy3Bon<5Z zY}}k5nz!bx!7|&(H0RrRZEUGnrWtgh4GZTrV5=F=Rn6LC(4fOF{Oj7C_II|bmN?+)Qm zEn|+{9gVWi!aywTPMs=gj2JF{iA6h5Txvo!Wsq84TuY->X%6!jx-4-xpdua8*k*`0 zVq%8y*7uiaf6+jC!E-Qg#647I1TvuD5^g0&YNo`Ck9FuTT>7fRB`0(-$TS)6<)3+N z*ceMscje7kM;7jMV&+5PD82AP^H)odE5CPLWV2JjI29gSqE7mlvQ2X>tQoQpyMENe zu~2)|8xqPPsOpcV{0=4h#2l|3|!7W5XYRz+E+Fs&7l)!m&>m zG!lov5R>U%1?M!m*^e_?6<%v>MOh(eEji#E>!Fh;$cry1tdjL(~Vz|HS}V0fZC<~J6OT;une<*^#!9tnTueO)e`)f3fQe88{e z8GPSL7F~D3_%R|zzW>dz6_O(#x)#0>Yw&ly7G7j{Ld!aiZ)Popg;oQa=Pkq6JA>Kf zkQ?u9?n$jd&vEi$C1MtYYIbMma?N{v6q`TBz{S>xt5=gR45S+wYRA9#IllA6>Y?r{B78EU4F(E zZ}DQAHovSIqejmcM_FbrFYb^WR-LMB*zzuZ2!AI+I7P8p26Rgj{&)TzblSBF`ky;u zqyJzU_k4xkHRYbCmBh}IUSdSnceHyFOvC-R@nc$--7Xy@s)Oa1(wEnua(1ZY%5AuW&eStTL}VS?xTeVGQ2m z(e%ga{)+Rk?sd{TGTENJobJN&Za!}GvZjyeU#w}gTzyL(i~!kzytMaF4u?@?T?qWITIs8h|~{NnFxl zEULdR;D8w&lrD_7D+t6(451i;~ly=fK|&T!gqKNv@?%n zFAwRi_4H-MA2Uw-n8{2{f9#kgd*z05he|ER)KR{iJve~h?hZ%vm&Vk!Tc!d=c?oYt zx+kkEaHyg_-yE$g-;Aef%B9h2gl9OTbCzL2-$;&@oSUw_l^We>spj^Xo!)0Mvp9A@ z6<%r71tZt3MZE`BeDgaVE=G0vZO#t_z3#`D_eSDb34*`jLDlNJJ>AkDq5IK&YH8M9 z<=wwO$H}+NDL08hiQ*{}K5x~QE;v|z19O(k4y1(}pQZa_d9`Nzyl@av3^(bWt}nfxMtoms5rLV75{hoeXp6QFa7I-D|MZnpoxz|A_(BS~0IQ5ZAZ>*W}# zRjDplJCDV_H`V(=`kH2w25{H9+3Ixu1|)8B#157ngO&dch{cPDoF=1eEMZJNrx zBlvKxE}IEIb!pCU-X7z}$--^24DBwSGT_V7?bz1t8A|^X{^VGDMhuqjcy>N_KAr^Q z=M9+qsTvxl_eN~L14tR7&(R(1IcHTn`kda6QcX1X3E$;)K_IuCb>c?jGBj<|fG&w` z`B!=+k%ONhXpO$Af4C8Uf4i)7B73ooc?_#m?M;hY)rBLigLD5{s`Bg7Tgg0#*T!#A zKB^7YH4}F2fn$h$6{~6T)Qy=H`8>ADf*zr*S(!Q?Rqstg-3H}KZ>G%UH+rF?F!Z8V zW%Iv!Zmjj#ov9!HVf^^f-scw7z{9?VJQ0+|=EJV5Bby4LQ-273LQW&qF_4}5G-7E; z6CS;(G&!4>s;z$wdB5L1{JAwqGD0RCeIktJT^=H(aSuLaKb~D9oQJ*|nKziA<8)sv zEz^UxrSu9~)I+1)OO%IOcTH61>U=TQl3u$Os#zcUNFUh)150fcrU8+v;YI_8ey*^UA}& zFnse4JpWSzVe+0kbMq;FRBywOkT3Y&&ILLJe^LFl>_@MM!oEs%PCWPsyS7TdZvj?I?CRQHeRb8mVKE7qDo=0NR_UN&apuKHk!2 zRQqcvI^UWPvs_e_+LKh1#Y<89LJ&><)a0PgU9jz?BkX;(xV>%@c!nfWcbj+!F3-bf zPq`ng^yYszL)E#AI9`7y`RTthBU>iBa}#GeghcSvn0CVE>8}>_2mr6Qtfec&SJ{iFieuXz}bonMx@SChy5$ice)+BN^hY} z;Tkonx+kys&PS<30n?178~nkD=bi{jX2wH=ya~m+z<#{%=)$npK8#y29>Z^}Qke&L z!gt14H9J|pB}llEaf{^rX8s1;4M7H=i#wE-{-QMC^6h8F4TAt`#?>`Bn zvtZLI^_a3C0NJ5k6)I1wE%Rf91K5ve#KmxGb|lg}8*;N|5XV|}cZZ?v$bU-L;w1)laOa{V1NO?XEukA4k@3 zu7;+|^?6G;IBU1GW1Fl5b-hYobym8*sSa&v+r^wdt4^cz%x3I6Et%*k%h5s@T+tm} z*=FM|Y!C*r=CT!B?rqSlID7-`4_D*8EtR)j=9VIV1*uomS07jFqZbd zi{*B^_B<&3h>6Kd@%eTEo6PZGQlWFw-ab2P3>4|)tcqP|aSfh`@Zuq1di{9R(X*jb+o%A7be zVlmQJ-BfR+XZt&2s)~qo;kb~e8ixm3%5_8?R$tPBL;uebSk{P6l5LrwCEoB91KIDd zQG-*2`+OseFT%Itzz9e5%Q=k@9|!*16eP^kaD2Z!6ki&BR3lP_bNb$cxy9HT=j zcB=HM*Bu`TCBM}%hF?BZqsGyT%l0L)w980UUUi*v%o6{c^qqfR zKZ$lHqQog-%eGasU}_eK8%`}z(e$7uDXRoahh#~KX4=Nbsx+}gGcb>+g!GlXTIqb;Zm-7ggVRpc~aN`VQWX>^OFv6_~!+m zF*!V_myB#HeXfd@9PZSbn3n6r`DT)5e{m4IL%ynZ%OhAfrxuUqZih*H7F*hnd!YU8R_DOu98=EQuZa(K~yf8W=kn z_WSptq?i2Ozdph6k@l=U-x_v*TQe)wgyt72RFR3`X1&fJ>qT8=ZhD5VcESNoF{5Y0 z+BC~qqQ*TwjS_Kaxy(F)j$RM3y=4K1)wN^q8r`|}Ni!ImTCnhquu_c^VBYVfW|RFi zb@Ylx9PQoMrLs4_H|;7}-2dPC5|Nm@3T-FNQGa{oV|cYt26ya>&BL0iM?-pH-Q6uP z54Po=cT-U}B!owuYtXQPHf#Q3GdP1cljQq2 z$%%hrY*;lSfI7YPQ1;>%Y-=a;^2vFqab7yUex5XH+mruhnsR@g@3=j)H*Z#mo3yt0 zwk#*Bh9T2l!(00!DL%y<{j1AIlod{P3ST5oX1oD;n|V zad&>6J|E>j!kIS3ldH2qQ}1fH9D5YStLmZ8`IgYBcNt41`*`eZ7(Xxnj7h`RYX*#n z=Ng-n>RnA2)GO}*Cx=C7Y?mn9_(FKpJc8abyN=A5hr1&kxb5a&gfy9o{7A*EwTDV3 zBA3mKgriik7XxekRMw$I_%}w6h02?Q5A48dzt)JJsLMrP^znRTcVYK!fbqS2aRck{ zkCuU)GZrGTa|Z8Ti;1!iTP6ANaZNjMt*|@Sj@4%JHDgp9aplc4BV6u% z6#k#;@K1wKo;y1ScMetIbdU8IQDX+I$9H30?E!2mcd?O6O!(*10?nB*_0_HM<570x zD#p9)#j{3mlcWzpi%kk$d*-->pECO==7GuoJO)Y)Wyy=uY9pA>&=T!X4kO*AL$ zPI~XYNj51J2J~57*3~%+zXjKE^7&%qUbzU1+j1s+>7dS>_ClLe@xq3cY>96X!mb=b zpq02K0&4Q!O?&1HiQw~*RXBFsVJu&82D#7IV$aVy==V0AeYc#KUBDRJE<7PFE(hrb z1)-aM0K0yZp4x;}=v$)~j_D4=YF{VrGO5SyKN`_$Nirvxh>L7q4*v8u=H)jJ5q4pj zI?+vsPC0E+tw;-9w?;BG#8q~KuEZnBtT<^Y-N&KqWmtjp@1`L3f{~_W)?}1-u;N&8 z;vLPfX3aCk_^WNg*(+AS&VC!p14km&t~E}-5x<40CA;47CFX8G_WM#?HV)+U;o>jZ z`3wDjir2yNHYQ7-#$$YKZf`1`-`Z_yX?+%kiN`w5SHxehGbeMY?j);y9M#SU{93gdGXo|lGmyuBG)C8g2flsI}W+Vk|o zmJI$=2p8GI5BRqhGdpRJ(EpTjUo4*5S$^!ae<1A-Md8T_L-t4tX3H7k36tHf@8ex6 zxYs>&w|7PP;;szZHxW;R`>LDsTi|QPB=BPuUK8MFM6EUWv#u^bl-sb{)TihZlF!B_ z;S9SF%I{%AxvID(%=YDT#E%`&?CZff6U9RU;f1+0VS@=%p_hLZdI?t8TKF6v?34KI z$T^q|y94VIaeSVyjlZ+gSkz3>zGxTf+eY#H*cguNGFQBFf01`r=GfPLVbMLxd&*&7 zt`lDRr3Vqzf721Ck2h0yw+_RHt@$h&BEC9@GOw;@R%4CJIqZ=<&$aKPymy5aNv<=H zo+q|p@)0|=ucQq-dFb-==0Ki1xf7dD_hN^wJ{)-`n~mmY@>f4Ep8vKUI~LSe&Ek8Y z=Mh~PO%GwjG07683g2*~Hz)aLsB3qe+2BNVcDhxp9yS|H_w^cTM-63Z_u2?s_y#{+ zrGvSv7N@NW7Z>DOyzX-ojyChvt5Qpb+;Zp0ezv?VtgRCpTJexkE4FK5!mj^1pmERz z1P7+_kL7!8mt9@^#vvU3(22em9kAk(H&e`_WCta^hT10V9~+6TkpVR5smNFJo$=~;D5H@KS4hth+`$j5O7K=wD{vZ~t9?F}^ zYZ2^OkFDFkg6q(0>RI+ZbTIYf`X%CY`<}(7DO%LnW~fftrRX?yJiG$NV9SX~*mmnY zj{g67j5d*cx(+8M~mCC<>}e_cATo_H0|JR#@O=seZ;e022rNWW- zVBFr3kq@V$)kh=P`&Hqf%KvaLWhbsDy~J1lcHB6rT)q11%MM`&FuVS2bbDNl=gt(t zcy!tuc-m-jM~>AWzN-T&5OtYk0~x7oONRlLrNZ$2b*_4)%UMjgfTCF1wU{)@$X3(;?kHtU}k&S*p! z{bq`T?$2seoi7gQ@?yLmlf*@#hWzx&OLzn+w7MS()2I7UBfJ7DCKO|)aENZ!7%eVq zIe%_<=F6^@^q(l%jiM!RpK@N)QTP*+of2qm+7dhUf@zYTOos$VJ}dYQv%n|FPHjem zPpxR->CZYrk_k#2gUh~loT)7ti|?;7uxCFup5x1hRyWbGegUJ!TQv1S3M!UWYM519 zeK$S_cO&T>j{gp$n45@hG>Au!-%{(JiZ@O6boLtzd3Luv7cCw6JW;qptFt-jS#4U6 z%z$1`Gc?*{$37L`ad;i6)!&5L!knyG+Y9lpdSI2jLt@-M2`6Y0YX6k?>)tx-+(Gho zg`?FX+3%-Wxv0`*8Yo^b!Eo1V;kCkv*99}H~95n zHg>EVqAoqPQo|Ak(&zaG)Yd%|{KFsLZuR86mj{3c?wmO!3y)_^!`?n?G*9;! zKt44b5!8jFwVKoS!#7n$*!P(UgSdLw0eHSGLX}S5nAz$*p0CkCPkAT#pK6U;4QtU$ zzG)wC8L^4Xc$3F;V6_0_L-?ZMOn~u-9vm@*%|e(bZ3vI15hlily?Y|h_3n#9vKuaq+%A09NN&^f;)^PI{QO>aAQc(n<}|~Gw+EC~`vji4-ie1V zXY>2?d|sSjgF{ccvQF?2{vAA!W#?_>J<^n~`na>reseafdRqm5?8cG>#*A)t2=DCQ zYnt{jRXTcku#k83j*hulRi_QVnMbhTr0kWF6&eITz%V^`^}bwsZeIs+oAqclJ@7NS zy>aHMIos8tW^u~gvjLJ!d$MQx!nXN~Zouh6XPPwni2SF$S?aR@ix1|p{eCxW=+lCc zzaPTjeoJ~cSdDSweNGpy%DDt1gja8avp;HhpX}3)zub?biFr69EM61Fcn#|VmVuFB)7n7phh&0G^uyvQ0~!#-ovt30HZbmr^+KA3sd z0QPdnE0o;k@tMszb;V?8TSX}&=??3*jb!Gw`&js_1zSwmh_6~f?A@afkpmZD!mUDe z^mM3rP7T<@eS%uk$WO47Z`IV1#@N%j9)tRdGpfNkR6L60hi~<`td=1k-)~QEac(^i z?900=8o|kUg4)zsm=zyRC?ks$TJI=emZmiqY!oKln@@O`ZNkz)etZpa^tX^vZQDqk0?5qgQJe{DE1rV%gSt3+J$I*c{6=L|Dft`5`2 z?~Nv!DaVpg7G0M=j`d;h4Z3tpJr47`SCF<>i;2R-b^jKP!?z2uPgm|SI#rN%t19=V zmm~FfbtZJNxi*(k|6Rm>%Y&HoQwQUv^Z8ReU4tJ; zm&J3M#%I1X=cV^)c2VXqzkcJtNmDRw^Cpe2$4lsU$V82tU}_Dn&iaq?P@}OIuiDsi zqs4ADJj0X8^IM|w+CH3=yXy3hSMjO8WT0M6S5E`CAk;cEP$SI}|qBH{7G zA{p0ri7MK30Yg*L(CP6Ab`d|Tv(+`tP3;Nl=nE~3TvLHzY9rphIgfin zL$&^LH1X~Uw_^?{@Cu@u=Zot-W6-B&B*U*BQkAXVVV{mSv=-#hB2t5K1)tRB8+zOp z_J0nkk#hRjm}3u=Lvy(ffB4Qu%1hbjb+V;h3*j_2YC^qN9k_UZHNHET3bTp(FzRb5 zuH*)Cfn?;bh-25^ehJp)x8tgA?%XmZnDt#Bqg}s+_|GSUJ$l;k&B|CV?Y;-gV;VC5 zXLW{TcuA++m`5dJwZHBi+z>|SB;gf*dUFq&^+&MOwG+Ao3}w@WZTU>7Kt|8=@cF#> zPA@c7rLU_Z|7ILaXAfY_;uC68bPbfr&v^4q1)8ppg2RxnaGutmVcDnE3h}M=GzjJL z&4cBe`WYdIJJB{qtboNwRcntMSbf}w)6Bx@>5#%pdu`F8WIb9pnWfBSCbG05i93$G zP|m`tX%MmytpQu^HNpAHcm|BBL`5xZ;Qnc3i%Kms8JbeoxEe4WAwy zTk=6uSGy0_2L^G_uNu5`Y@awx7T|kKJZn08Gi&__m2Miw%qT19ev8oD?42NUrqw95 z?hALPKo++yV3)QX#0ziFC%Z#wZtAY~-E7GVCSkOZIo+3}wg`$GiHp}uy-RD|Lg^!2 z_5O*l%-nR;o0{bES}iy(PY=~XINq`f11kquv$K~ z9{lkhE?gta1U+u*XN-Fd?Ko*&7wK+T@n(-e){{>B)AN!c?!Ok!f2zXE=p}Y+l{{sO zN9uIJ5@^5H;lnO&e79;Z$ZjamA+nfkV6 z37*Fjx;czII|c!VI`E6pE}X8mP#ut6bK##VT(&ep z@Sr;EryYTn_uVv`eeS^DK#zZ4T5x$^6Nb;;iYGQEG&vi>ryG(PCwHo=x2^d8YKe+% z(?&h{dRRrqJ=esfPQgnx9ub=c^40J8s#}zJjH3s5IY$(n?7e1x1xm}~fIkYH`U3$wqy|MKFjs(cw-;nJz;he%07z$^G59=K#*cdHC)-qB3@tz{F}0f(I?YgVs6pj;N|RyxdWGX@l7IZ!8>U zOIG*6DMXHm;=Y5DH?tKEo^TEdeTU<1o)Zo(-mFUYjDps-kLc#plz)4+VfV=s)pEP) zu$ke5g&Q@Pc4{YVchsQv6BoX3xf(UAZN`f(b(H?)Pu`=>^;E0=9nwV3sn70m);y9q z5ZBt)G$M7$b_DdF2`ypnRKt+VN;FVnim=Nj4Dp{47d(N2?+K1|6LSMssA&y`Gqm+x7@K6$urz@U zg^l-b(Nm56F>$84%I>v5eAI>}yxgb>TEDES#@QS2tEFTiJ_#e$=b@Y-ik z+(j~00XJ3nxo6M}KdOq?Sn}_R+QRS(;jKIuy0#1E!-na2@6m_80bZQwG(#oX2`^3O zgl68(B=!#chsN7XxO8|KLdQ0j+{ku(ahsy78kgfm)*Fml?vAQ+++ZTlsnrq-VPFpD zS+BFmx>Shq!m_Nn_?l+s_e{(wjiHudCl>40RuyCGai~>)ZdknnSG4TB46}A)tCIfx z$`p0)zW67a#Pi3F1*jZmDcl)rF4knyvh=k2`D#DP_UEXe_syYMk-<)HUAQYb6iat^ zWmfD+%=sO}T=B&2G7Z4vQeRx2{|xy#_Vjp|#P{>c5Z@?(&eJVvuhW7~1-IZ>Y0iu* z+wig393@x*GdCoARos zIY&P6W5$m+II-ZKn%yl);7>0xWT-oq>1=bY246+nA^V5{ z{|cjNi$fP4vom4FzO5)89nb5DF{m-`7nGhkMyGDU%rV*+X=cj?-tX`hPhlnV?!RS& zP)&H#TkqA9{gd!X-a3hQR5}3z9nsWQ`XI;j@h8Su_DZqzw(ypGY7z3Y{n+ifZ~%4F zX!vc8>_t1X%H)Rla(Ir)*G^&eB=JzE$3f3+7A!0b*#4M?q3=9Z=DxGy!3$P_vO6@K zq{GZU*I{~DGUNRcSm)#sjGcKMfoFufkkXD5;*_caa`*UyzkeJhVMN2Ekf>*pT1yzvvTCN z4dJ?(?=kA|ELHT;nI3Y_D>*|XEVbkWo5#>T(t>uoyYt%H`t*1d#m7C&xU1n4m^ z6e4_tUusvHI33o8^QB}D&Tl^hqwBfsb84!_Hcs-xcE6OTow-`RFBw{O>T%w9J-YTC zEc~E;41Rt?>3W4RP28+?jtopNgnHAT`i;v_GNvX^bX5%AD*br_e{St(K$|NaF}-nLI{f{O z!}gC+Qe!!S_C+v2vLy3Dmcl1l_G`=B`7>g#ipa7WAVrCRo~Ncnc?0XPUDj`jpDM^5BE6knwCJb$!*#4 zt^B+4{kSsPP(0UlnG^H?aRGDTJE#p8=$7C>>+?t)V#&f^m+=8T+1|b?4^GfS^}=wK z=M%x@|7ke2YCi3~SHkjdOLqSk1N&yVY*P_NgB|x_7QP1$@5W)mgG!8DxDiLQUD-s= z2=yLov!t3A3maK5`nWekmI==^)|D4K%kI6n2C+N|9sPD=ZCEK1LXuefzf5i)cme6{ zgIRRTgXWnlQq_&<)$GcM=%edDDhE$tzin$kq;zK$bWL`6xOS}LU^r4X`L z_Kxhm_g>jETXuYtz4wa$_4_~TL9ZTg-=EKQo#%19-xQ8{Og!C&%Un_sFFEs%2UQ{_ zd@QUptYxRNSXh*XvwZM#VYtPRul1fI`%f`FVhOONX3+)Gz zU6-%|)8(Av-RhIjDJVy)r%H_ca0t4a1K3bw$|KTwzF>VZ`mP9Ok;@pgfBykCV%D&l+DBc~{jV;Fh6R8`AQF~i8Y};kS`&}B_Cl_)|#UtqLo{X24p`0aiy`xpW zil`ZHVI7yn&wEawV2>yF6}6&MhcJdE+R*Kgo#Z;oJMYrnNSLU{!_`4_9~w=?>|8#5 zEqyup_Eec=Bi{|-+_=A(hlaVqe9J{#O)p|?{YZMs&hx6V=A6H)6)h#d_WG;#-223q z34YDF+~I@xdUdkQ8@FKcYGpP{OW?deQE-Sz=f`c|aj0`MUR%_UPWQ`E^-aFZ|620Z zkPIdpd;=Pzxx{}uI%ZzSjHbhAQDuT92ZL$nBXe5|oY+^~Lrm8oj?y_T7G_;RqC7jd z%rKCWi2?V`y|*ue~PN9(?iBuYYD9(a zB^+|9LPFXow7%Aw?~d#f*`K1g#nFa?zyI(bX_v|RQpeNm1o&?Z_y=Y9{yeF#z#-Q_)2mQ^7AgECjAFWoaZC+>n)ge z7{b90&E(82ms1*7i-#J=@q=buy{iI|H+u8Xq66Z1=~l(t!NqXgw_KvIvigZ_k{Z#? zXEesEUBKqMpYg)r5KgbRflYa~m~q~Qr%R2P(7hiwo+y&@K|L9N zfxNFx5!C4c61=5Tdy_Is_qr<57p+EV>vC+2h>-l|W^~#TM*m+|5fc?e9X$uE(d;5; z7Jm`tUWNne)6iF?0j?dB7z~GG`Tzf4ZVGd&2e9r*F}IZp@#*>>sC`&3`mfUE zw+1Kl-`NtSk$sSSqm;Q@w}^lHccY)|OR4=F$xG9m#GqYWxco*qJ)&e5Xv}8u*Q^S+ z#!9B$ZRu25U!(}P_oey9!!U7cf<%Lf;@y@BV*S9q!Xnv;Mjr-ph`EyV)LUZnZWmsV zyWLfZgHS#Dun5rnEMk;e%1n>!e{Oq5_3+GO8LD^L=3+6wI0aAq)>|kAmc1$UY0{nyNAl@#LXEM`g7+~>RG3u^5 z+O^Q(wr3NNX&f$EpGaV|?^AT`sE-|y=A6~~3WhmGvc;xs_K0i_?_fRl4Yok1){@Z> zZH_!k8z%4pF8Q}*rsRBBg@$l_yd$-%$H{ruO)+HqE}@lmTe130IIj=^U>**ACKlIa?Gq}h?O~{mG`{(;ph*1b_x|a zj{{_1SBbY*PQvAc1bAi~#p*WRwCnAKF>`kzStpWhk7aXMh0I#`NQPY8F$`60%BwF1 zL216+{khj*{wfEAB&^2BvBNp@st=vpM8jz4By5qqYm>HGG{{+@nD<%ox*z$n&c2W; zlI5h={W^l<1<%AciY)~>9CzUX_8!Z{Bgwx~lDx_t=OSrdbqCFMYjUi|2)>HcUw&!JxZ2DTUMrPSJRSG8lTqn-^e8#w-X{a2r5c|!2#file{Rc`FDbocb!5vwuF9=O%6JEosUr9!C7Q)P!k1aqN9_H5}zV zId{Ss4AJ}n_nDS#xjPSks->TIz;H}IF3S;R&6a9V$1a&-*OUg;M3rUcIB(Z}3PCQIfsH4qbSn?^D@<2dU+NB zK80A^#~d9(kHF>8bf~>(&Q@Xm?4#X@DIcPkAa^Hv77jGJ)QLmB+hY1yC&q;+({1iw zTsqK}z0{hD8mrbYm(St?$*WbB`3Uz~a7+Q%s*f@KrViwc6IVn?e=j!XsqyC($@9pU z44dAg6?@-#Gjx@;*buZIYbqyTjO>Pfmv_+pHpeh?(`CiL{906&b*1ytGdMrjp5sHu zp?JzD9$!99F>U8>%*-i5_S0IZT1lU$XD%xXWw)@+A(1im8g`^l!(82+;`O{@F=D<2 z4rgfc4P9{PtNU3O=OJWHN5dV!st?qgQRHk@MZlc$#87=2=ysuJT25{ z@ zr^`*uSU*;Beiup~dn((%FoxlP4xA?Muw5RoABdrkzZnCxKH}9BPg+iBjf0ia zx%IS0Snb#&UR5<=*^zN@lgwqm4?oa2T;{}qZ3}8ak4p^4iOFwixCn!x6*E}bn=B61>_34fkD^J7b`x1C54dS8f ziUbyIc6TJ*`IpXwoMXJke*cxQ; zyk1i%7Md~Q=2SGB-IpD7+i;+gycZUn7GE#+;L{VDe7yLj$V^e=(GAWbc}`D7m{)rq z)m(;+o3{(I5hV;ZmFK#=KUhDv1MO=h$jxx)(~{#DbH!DEqk|JNjec zdx_V=3$fP6ZjnT#I(r;JR3M0hkKld)(PnpHInCF!|7<^9LMR&T9OkU%iXqS zoa%iV(L;;SZ}3zsmwp)~XA_z}d)$79m3aQZN`w~b)O8UrqS;Lnr|JF)WBJ8{TV(E8mjY&iQ? zjFAi&T|YId{|k`4!V{8r5GsyVm2qrLAXfXohj(pjn%;Ykp0*cZR^x)fPp=4z4WVLj zWsulVkj@`rRyh1Jnpm;|V?V4A({$oxe|;VXjxl4Wj59bD_*Cpv?oYSUC`QRXtLN(T z@_wL2?SFrvR(lye7XMI;-x4XmSACd#u|#$+r-%%n4l)<_L$uyjBZ52mvb)U)E=t-Z zJhue#d`NrN-g=GO-Q1-A^a^^8Y=$HETHt~Ca(Hb0Ej%u1aNCKNyuC4y-;b(sl|c~u zoUcQ3(>jGuxd+Dm%VXuzP$oFc7dLZdf41i@*`4fzRj?@&iBo~lC^{cpI{HIJoL zRy^XX#g0R@ks!0;3&Xyk|H045x3%HXh)p;l-zURos`LK+<-)Oki}2}M3zgJd`5rfs zZpV`tQvVQD&o!v3Itrx*eQ<1M9-0}ai%$7E9K37{suC7K#P^ac9$g+*)}v{Ds&Ja9 z!UYD!w0I!GZBp-kq&mTB>!#vm@( zbslMxs{u5fC?Y4zT;QE!eg<5n~}??Ibz$!B|< zhyBxx@qGOjJkZ#I-`i$FZRJeF9sdZui$f*<^A}WXf~Z(6o$TF5@X@Pr!plZ7r~ll> zTH7|lTmK&HFD*lA>3vLc3$Dv>G^k}EX4VM>SXxs53bEh?_|6E-7 zsRxg5Zd`k)8-L54-hZREBJklLblrUzllOInPevbnc%@A3%|~(M`zv%Uv*5u~{rIV9 z5L>-3;DLd;lEt5ogKs}bR^~>yHBIC=`58K0WWg7cojBfLK8o%=#h|P}Hg;N!Mf0cN zUB_lJBO*C%BMfoz^IzPTY&L@%TIhc0I~sd-=OE=xsC2O7L}g{Uiw|Lh;c~Ck|c6XJh*hNHy7v<*o-Xf8`{R zxHy;N9wl?!n#ZEyw;J0V@??~+3Ln`;a+jtmv#gytO!b!NZkLU0r6$bP`h=Vtx#E;` zwm9VinFa4$~WnRA* zGIcw0uIfDOiO-`-xBe`!Y=Fm1$zSVsAD2x_C|utl&CMUfoP*db&XPDiZ zi|5rBacR&J@hfWx@3`3F+-wILoNUF#NeV1%AI4Etow+!7rf5B)4&CQc+_Lf#7;#pt z`5MaOe>=-LSQ$&YNT*y+OZ<-P$VW$#(6X5WX8su^cZh1N%8g{C_vgL)8IrTC4HKDle;p7_+x83a z`if-R)wrG(~FNH&LYfb1S6t1q4i-+j+oR8Kd#BX@ZDnm7}1K;PmVxiOEb>t zAIN+9rfgv%&$;Stxy)MjfiA~#OUf@X%-CO1s4@rco*GPA_Xq*qzhQ%&0Y64*a+J&n zF4x*FjDD_#`_UQxwfj!uf4(lurXO+gSCM4Yx1*I?Z|Mt`PPLKi#H93xBDVhvBq@3G z#TMyP+4CMxZhyzUpDw)XzC~O)mB3Ia(acbtN5(Hu>`c+c!1s5c=Qb6io@-){P8oH4 z#tNSe|B2_1i4dJUdO3or2lg4oe{x@GH=%0`j&9}I|Mz|r5!FgiXVTNibKz2|3lufZyKCLLy?N` zZ)wBi?<>V9>2?Y%YLB-C!?-2kr* zuDsanD*C?+;R3@d(PqU|{|!SzdC=wsqK&m^*6x-OIWCz%aq`S;5FtHWh1_e~0`<>33TLlWF4)+O9h)c7@02E#duX!LvMA`= zNT&PSHn{f3jq5(e(RElJOk#DZEKKM~eV*!jR-to#9GV*3LeG-Bm9Ukarg zLvkxO4&^$z!>E7fL$`A}j2oW9IeU&F-5{0C%$swr%~zDWe-N{Dy9mYpFnYdLh1IEG z+Fntk_p#n6{NTbHC8YBa8_Dr6qlMoBthnnTp5-sXDc2GF@pe3}wi`j6{KYVxB-tMx zcDy9BsX=WzaP_`^Of{DbwSGgna@uTs7}b^^CUs_yc~el}7Aq!%jm1y9w+bcM717lk z#sy0{(!*E@vwG#xtKpM49_Pv11195Snkt7JlJ>M-o{;no9{aoql_?u=ZE;5~pS&K! z%bSbu+P_g>IbK}+6v45lDv-L^5$(oSii!*RoMETMAC~X2Vwpbjn$1P5X1wg_hO#F0 z6TEs#-gL=-nDSnB8y9``-`p&KIahP|a+!SQFHmK=?B~t%OQYAQKJ=fy4ULnV@X75Y zc9c1hGn3-+Q!@NL6T;;Aw;T1wPe$U(bE0^KqfqI$ALct{PyUqT{I$P_H?5xePuh6` zqkLwd=l2v2N;)gznyRqRlW4RaEi)ufr{k!;Ge2FZ5iS4QjQ2O>JyPA12kw+`U0E-V z_IZJ2vSVebF_H^oOF87K76OKy!^oW9FnJg5|Gv?NrG9yAB4fZu1Q^vl+JDGHeH)7txmvqLoFIqyfL#~5<|{*V?gU+c&|4dQ`hKG9oyhB zLIJ*(Z2dMFY@A<#r-`cguk#T_P}~O?T=U~_9~(N1`k%Aak6xR!u*&){p7|;9qG7+lbn$$sjHxzU#2oc}5=U7Ra+Pwq=G_ySG` zbY+W&u{@%YBGgWlPuc`US)BC+8>* zY}H`T!et`IL~?RpT}FNFFz$XK=Z!=E6DoP3TzIM-DjyWH++u4M}a{SmY zQ{axw^H~(0v}1HxOU~^vjDMO-9;T9XG(9Px>c|{U zcRZ!YGX5<#loc~3a1DfF6vy3OC#-dbGRO8C{@Z^Gooqa~aZG29+ZDz)-~T}CoI=rK zvH^dDEEgMpED^0NiaFu2Ij6Mjz(4I4;`#Z(JoU$kvoBf;SL-mz-zdcUR==@Hve`2w z`!}m(t#~MV4t?V5 zQ2za~%oYuhJIE}a5}!p2cWo$i`ih?e*NE6z_h1wM4_zE)!`b77ujw1<_8!`bLeZ0- z>SWG-(S10dy$i?r>Fn1{lf5-JGpIW9VG{ z1MN98#o-MjIr&sH*ULW5+sf{k_jZlAesqN5_tSEe27Sem(E$v6{R!6B<$JMCnU{{* z@bkDdSn12Y)Zx1&H@`1L z9jcId<}FlC3#iIFQCUo9ab&T~We57QGSe2Be(x|jdKo-UN3fyV4Q(H+MBeTN*qAEW z1FOIJ4R{sLcd|46_i!xZJ2hw3qdcbVtbpe$b@ng>H)%EFyrK$`IkbQdx8-7Wd{Ujl&R@0*Q$-x2+ee}Ap#*+xjFi6K_lmo*rYw5U8PR4* z^!c+3w%U+5ES#iIMGxwc5 zh?|dhD%$@SOzWMp%f4a+KYX*0&!yXloA3}PO=9sXPR^(wrZd$^1tUEa!eaeWm|T`U ztbrNWbHb9_cTBd8nL!Hrr;X8z_d(C2 zCGVP=aEVea5`Le@)+O51eihBxh6<+L*XHt&D7wz6hsB~jNN*boy?Y}#v5RygXCKAC zkMH5U+?of1;<3)7DLm9#36m`^5VvM7{w|QYoRlmMzrIr}f27O}UL85@q$!+oy~U0d z9l6pa6m1fm7_w>}hIk)FwVX{Il_x@P?7;X258N@G0?i#tygEUFghC^>y_dk&9iJ%j zI?uwLC%@36RK6oZ1Ye#s;=3L(RF!v-4H?Ne5U$Ok|Kxc!VX^q$qc=u&FXXbsUcAyX zQ~Ch5ODEoHnAJ-EtggMN56tE9MTZfY7sEYAk74BadMs>P#GPFgta7gv)m?n(?Ny9l z`|2_0hV0}%G(*0F+`ac~$H9lsi7Ax{w4AvDzP)>}*e*n*9KSLtSq z%;HH?9d7^OOXJ@K(wqAcbB#{mmstSc$_${2W(=y2`qAB6n>|;|LC;gm;65^ymD0!h z;f&m$pYfMY5`U)cm%Qm9KP0Is^Zg3xl`dYX_?{?d@x3o%VUH%%m)$bE=A&T!-HH#! zSjrr=+}S5Slg?NVSxi0%(@pWzn<<@}Z3eSnp)wcf=8C`rw*LFOti}A(!Q!Z-Kh~%Dss>;Rg06~Cg8A}6%Sd>6DRDISs-&_ zJ3Bv6)ZJ4-V)rB}_wGow!&!`dr-AK1LWNfKYiO+tKvdcQ{9L(I%zrunZu*jwD)T?d zA@BVy9?G6<-*!xtxr;F?rFXuv2epk1xxB%Udb0-erLS~;KS`DR@!R6>@FVDOYXz44 zyn=#M12*l~oANKQHrbDgXV=g(APpP8%1lT1cFfLhMPK`t?3|O2Z{KcXwCWx)@#|O| z-WA2c@6Y32#{fFtG~xDhOGQ+-)6kbblj3Vm3{#iBpNu-OwZ@rkmPqfao(V(CaD5`Epx4gljCH5st&vJ4hsMO zo}u=GoL#mvu8=&lzns6@3?X1BecgPF}iB37}?~H z7_%-9JAdZlOV)S9|LnrYcEdS$dLAd6pT@8aMp&pEA$rY7;)$dzmN<0fpafIi?63qK zKRgwTvE<9We)wOFNbG;2FweEo{yU1tVRLf<^&+`vGvoOoLDBEN)pYfG-; z@z4{{limGid&*cV-L{t+<*sj8GAlmK!;{8Abe#4Q_8T5zZI;X<#vJfJn%V>V9O`hZ zYPa+*d-F|t6Xx92;)IZmXkX;X+GU^cDt{3DZactbyh3stir^bO74vWH5-W>`-m`UBPLPT^IjR5r<7jFCV8LRGgF)-BwNrQ=;CGpv-=Hd#C`IhM!v zHsL^LB~}l#7D*#paMkt@=oiZyrtB;_7!6|ZdC9D;)S~?@FY)1TEH0!hmV2{iyqWa| zI(nm+U}nSXN4hY$<8Cx_k~`6%19|7dacs{rWJ-A*G+cGCOm;!Km|YY`_VHYou3%CR zh*kTF8S$%(Cd*41dweu@{aKC`W{tvsfn;Dm_r%-fEx3NToY~aNJ=~K1bgo;Eq⋙ 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

!vuu7y& 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 literal 0 HcmV?d00001 diff --git a/onnxruntime/test/testdata/transform/computation_reduction/gathernd_add.py b/onnxruntime/test/testdata/transform/computation_reduction/gathernd/gathernd_add.py similarity index 94% rename from onnxruntime/test/testdata/transform/computation_reduction/gathernd_add.py rename to onnxruntime/test/testdata/transform/computation_reduction/gathernd/gathernd_add.py index 0d32f081a9..ec0fdc888b 100755 --- a/onnxruntime/test/testdata/transform/computation_reduction/gathernd_add.py +++ b/onnxruntime/test/testdata/transform/computation_reduction/gathernd/gathernd_add.py @@ -36,12 +36,15 @@ nodes.append(add2) gathernd2 = helper.make_node( "GatherND", ["add_2", "unsqueezed_masked_lm_positions"], - ["output2"], + ["gathernd_out"], name="gathernd_2", batch_dims=1, ) nodes.append(gathernd2) +identity = helper.make_node("Identity", ["gathernd_out"], ["output2"], name="identity") +nodes.append(identity) + graph_def = helper.make_graph( nodes, "test-model", diff --git a/onnxruntime/test/testdata/transform/computation_reduction/gathernd/gathernd_div.onnx b/onnxruntime/test/testdata/transform/computation_reduction/gathernd/gathernd_div.onnx new file mode 100644 index 0000000000000000000000000000000000000000..5bd65f9e3f2e1745b34abbea9d8b877dc3ea93f8 GIT binary patch literal 1672 zcmb7^Z8Vf=7{_-q7!O;FY||ub(aX}1u@udHT|%r%*xnd1#>^wL%narkHFZMBTG`5O z+bNOK+Js)5RjRd7tzJmmi{7@4Q`?l9N_*;%?WCQe+WoTae!8#w!*%`s_kFJO<8ZiE zYL#lKfL%!}!!3V8i_Gqc$S9Ds&?DYonHLh`<& zFuipm_Fote=jwVvZ}$}PCd|gdy>2+)@*>pt-6qo7GjKUR1xBW&;M^J=iEoobWMcyv zBX+^(6@euGrX$>{;e)~M7UYmvTpU*ok6P6a*c*3U`Vf@hUe4Pp9f3!gL0hEns00 zH6FZ*#8_Ea1`T{K+!0(2N7JUl@GFPmg$dyN8w8`LI-*7OeHbyp1uiXDO7VUe$IF2bkF#** z$CKc`&H+y;B&A}9{F)WW-@FjMeWJrQrykL$SOZ+?jKqlQ z5(s|a4QCJALb}gvaLYXi0i!p={n+Wa^Sn2%Umb(e$_jEh&>1U&vLT|U2lnsPz>VHL za4MXQemNSf;)t+vU>xd$ebM`%6Zr28BX^6ev8CP%n9^j73;Y8TN}R#%_zYZdKO9$i zjKHJIy2*TQBZTfcCPGs^#CC+?Cp+vh_h2yCltqE-*F!t;X0eS+v37$W9@!`(Yd48- zQFIU7vMnLQ17z6cnTmOnHjqMXFF4vpVU~{>+MOJLkajJWHD7`Q9VQ??iSV#E4V@pm zL08CVFpMdOihGq%<<&>3Mp>epRSB_cqp=h^%5DS(eYV4=5#2nF0JzzgMJLFY|? zaC6+$IR-uJ^Uqhk22?)zH%YO;hJga zv=mxJnHXInj(n%%JSYLjocri4_y7sYQ7y@%a-AwRO0( kxR69jON7|+OG^q$OQbk5Q&RIvGD|9zI6R@OiF57(0Kd*4+W-In delta 43 zcmZ3@{F6zDgH?zpKQFIBH?<-$w;(6g>g+@z1IEaS&YG-j`K2WV6U((Hp1TVGEZ7e= diff --git a/onnxruntime/test/testdata/transform/computation_reduction/gathernd_gelu.py b/onnxruntime/test/testdata/transform/computation_reduction/gathernd/gathernd_gelu.py similarity index 91% rename from onnxruntime/test/testdata/transform/computation_reduction/gathernd_gelu.py rename to onnxruntime/test/testdata/transform/computation_reduction/gathernd/gathernd_gelu.py index ea97a62886..eade1b868b 100755 --- a/onnxruntime/test/testdata/transform/computation_reduction/gathernd_gelu.py +++ b/onnxruntime/test/testdata/transform/computation_reduction/gathernd/gathernd_gelu.py @@ -18,12 +18,15 @@ nodes.append(gelu1) gathernd1 = helper.make_node( "GatherND", ["gelu_1", "unsqueezed_masked_lm_positions"], - ["output"], + ["gathernd_out"], name="gathernd_1", batch_dims=1, ) nodes.append(gathernd1) +identity = helper.make_node("Identity", ["gathernd_out"], ["output"], name="identity") +nodes.append(identity) + graph_def = helper.make_graph(nodes, "test-model", [X, unsqueezed_masked_lm_positions], [Y]) opsets = [] diff --git a/onnxruntime/test/testdata/transform/computation_reduction/gathernd/gathernd_layernormalization.onnx b/onnxruntime/test/testdata/transform/computation_reduction/gathernd/gathernd_layernormalization.onnx new file mode 100644 index 0000000000000000000000000000000000000000..b817a0e2963885e9bcea476ad13dda81c3490781 GIT binary patch literal 1743 zcmb7^Yfw{16vv4~$XrN^7nB&40Y;0B5`~Ha=AJ(|7R4%xS`~`KOLB#4lN(6FQ$gFJ z4uTa?tZ3_?I6e^pDKb7$YelNgR2+O`MX@@qkMUXBS{u}A`>DDgcK6KLbAG#L&i)k& z*4-jWS%E?pZ%#D{;T1~ef{f`dN~!5~W^j^VwQB{*U@;0-t%=We%)weqy4~T_j_)#K zELO8NQxKC=?2P8kPA7@HjdgpTOfNaYgIG5kpCK6aW`UQ2SoVb>N*Q{a-KfvttwCz{ z*QfPC{_HC<0_=uM3Y78d17DDpmLdvF*5%~ zGd}5(EiGLTa=Q4u?Ni5MGV4<W9fhiuea z6@J_T`O-=ycJv&ACw+&*eCk(jblOAOw>J`zNr&m^T|L$>Po};l!;qD?g4=XG9&4f^ zX>M5vZF2XeJJu#T*Z&r|PkzRQM<|g{JsD?8a`DdSnP~OsMZ3a>z$vqi{)+5HrJizR zJ&41VfyZ^JNzqU_d%?KY3*J{IBKgF0I&H{=c=0loubKdPQ5$WmIZB^DIz@r~`q9An zbu_naINBesr}I57QG(Y3uBrF}>8|K#^N36gxc@b+Ip_v<_c`K*Po#vL0Z7_YOLy(3 zsqywAy3`uT`KZ)rZyQTH$L63mG8o4)s;N0+Kb@Of${kK@;FjNxLCDjQX!5>DXYLo$ zu@QA#*j5vYzpT_*Z%l(WLWf&^1+*hdiJ}|TR2p)g3!LeKmD_omxvG=u5BXyN-$~9t z^uc>IzSz@zo#rp>NrNW)W9CnxI9Jq81%*ja&L_kTt{~^8JbaPw3hh!t+ocwrWpN7` zWsP(>(}I(S&(o9=fzCJfroHQX!_={Xw(Pq>2Qvb(vGo)DxY-E>%3|Fwp+oWg^ja#Z z?E~Z4XEf%j0xeZWvM_fkxSNVLDGf+yiN(+B{4jOx6-rz5JLh>vq{JmA?744%(c2lC zx|faf7JtyuHYc`Dpi`9+o;Hs}=(l;?>1H_+__^fSFaV}yE!?o!UfB6=1l4VK#jd;x zV#%4IGS`?;*eSqw-zPQ)kLAk+EsOj&AKigZmytsK7{qZEMjy8hK zDr^bxfO3zD^E}gs3Lf=ETuBGz`!Q(VWyR697J4#6gVJRNjY-;N!`2NzRfY!m7FA0cmVi4x0)V2q>X7iRmC`C2D;^LQVqo+{Be zaSI(#XJTGw6ZhH3d~Q^U4{opYfgwK=2UchhbL$W#6xPt3Z#eAE^+ICYQ1~8StP^YW z*jA8zJjW1J)pKEqpE%<=e(Ivwc|S1l;#KRVL4(#)M%3? zp!9Ms9{Yvjbln5;S7pODg~7FT0f-(~Mg#TXi2Q0G7f@No-CN=YX0H=8@$Ga{7Y%=> z53we?o@AG2A!MR69xtpWt#TY1{W>_;F)36SUQK5N7c8s4N3FhRsY0|PKH#O&vp!5; zg^X1(u59<`TE-|?7n_h~5+ugiAxZJE|ErWkm_UUq`~K?;YF1^;mUy#h(5G4jqiE<- zRK3BHF4>uG3RzM(^HLSrp^Vl6*SuM1*L6n887B|-Q9T%?!D7}r2v&>DGTZJU`y04_ Bo8tfg literal 0 HcmV?d00001 diff --git a/onnxruntime/test/testdata/transform/computation_reduction/gathernd_layernormalization.py b/onnxruntime/test/testdata/transform/computation_reduction/gathernd/gathernd_layernormalization.py similarity index 94% rename from onnxruntime/test/testdata/transform/computation_reduction/gathernd_layernormalization.py rename to onnxruntime/test/testdata/transform/computation_reduction/gathernd/gathernd_layernormalization.py index eb63c76902..9473d05010 100755 --- a/onnxruntime/test/testdata/transform/computation_reduction/gathernd_layernormalization.py +++ b/onnxruntime/test/testdata/transform/computation_reduction/gathernd/gathernd_layernormalization.py @@ -34,12 +34,15 @@ nodes.append(layer_norm1) gathernd1 = helper.make_node( "GatherND", ["layer_norm1", "unsqueezed_masked_lm_positions"], - ["output"], + ["gathernd_out"], name="gathernd_1", batch_dims=1, ) nodes.append(gathernd1) +identity = helper.make_node("Identity", ["gathernd_out"], ["output"], name="identity") +nodes.append(identity) + graph_def = helper.make_graph( nodes, "test-model", diff --git a/onnxruntime/test/testdata/transform/computation_reduction/gathernd/gathernd_matmul.onnx b/onnxruntime/test/testdata/transform/computation_reduction/gathernd/gathernd_matmul.onnx new file mode 100644 index 0000000000000000000000000000000000000000..f683cb73cc20cca16ba124160b4aae26266a9310 GIT binary patch literal 66013 zcmZs?2Q=1y{5On9NM>2tq|7M$`n+CAA)=)ek&()lm1HDoEA8}a@3i+`QX1Mtd#Pwg zL%aKXKhOVp&biOI&v6~sa5>-c`Mlq+^={WryM0<}YOX_kZcIvga=h2>5=B*aRi%W~ z^z1BEos^iYl4u+RFd)reVAP_sJ+{i?+crS;5)Ks?n9s_{!v;7Ia{>z z|9?IS>0_&$!ytD&fxr8o!r-m~pF>+j z-jbfQ-*F1bkN$&JO$dMAx8(sfSY1}kIQIfZi3e`}H5+Lfwji9|mOaPVYI zxIdP0d;K_Tnm1&V-(lpvMfkA7kugV;_%*f(N3IRWxv=#Zb#fCl7fr`89c$iW8=NTD zr{aI*SX3e7u;DJe+j9`__iw{CcXW8A`n)WSe!TJN9&*=o#;&lTRC?c);}mDWBt8j$ zO|N3&Hd~An7Z5Neoj*3ju)Cv~7**Yt^PYag*&ljTsU6PVSN+7UCmOUBck#6-mhoHV zxxB%V${$&2iX>vuyezCjIJI5(}+lhKYWUL7y9GjuyT=i)13z{ ztBG@uLn&L;jrUa=Wnb33MSb2ltS){guJ1c30zTv-ue}~$$;|=uM=;tdiNUcceDf+# zEVzFZJv$n5%;qAldg)HxBO2Ho)Poj1HF(S{gx2}xxYDp(mgq&cIM~r}ZXZN9?v^!Z zdDCA*nMdw;XB8?&yu^=L6VaI5fV~ftc`|T~sBux@ zyAG?+F3pb1)8-4a-C^wE*(|*MU&>bOJ}XZ6_Ff;EAc(j9L2FR-oEb2wJ#py z=A#~*{Xrf1soiMQ`J6a*D32|8ikMq*=sJ54zcgLK(sFY)eDP+eN)gYzaO1ZBCbIFc z929c;E%>u8 zhxp!)LAu9~@=ldjkCvdcE`WN|uj1d*C7ATEjo5Qak42dUw9zd^XiOjK_6(u>fMjN# zIVBo@d_w9VPi|BUVrRK{Xt{Tw;_iGn^z-AUcKPT$_7h6K_u}naY0P!@rNXXIo^u(? z1D7ml_h|^Va}J}aN{KcK!$snvXnysWiTj=l#D7m5>0tW?<{yX9qi?dPzMaJwFMV7n z?L*7FIq1D+25iq-a&f!{Zx7LA;ZYZAwD;k)P!q^iIB-ryM-=5~bIrO|qhJ|Ie3IF#c_qzLTlj_v?iKJbx{?sjo*q0k9Bb7e2j>6Vw$cCOZQre+XnN+EgvP! zd%GP&jkH*DK9%M_W+LEXBZ||N>6wwjT6;yDGgM{i{(0WUXCI11|GZdQH$~f(h-77;CP?`!hR=iwQ2mrt}Xg-`|CTbr|(V zKgP5gRa!2N;XjpjxZC1@A4`&j!>|tQx@H6i?+oDT&*b8-io&le@bS4T+jcrFyLfT} zS}s+HS`#}S(v+it$e`S`PHeM%60(+mLv`3vOlehT?a1Y5cy7y-wlVxW*B0w{*-*zS znWq>25qnZgMPMf-en}m}lNEC8GToF_-s#Mg8F0A&4UrPqQRMdR%Vw)u4BTyvA?nRI z6>Y?%;{HtRkid@(3RGYA3Hxr_@RQkn{Fctor^k0RO&)+r`$q6}=kG#uh7Yxq2eD;| z72P+s$H|{kpP%?ocrMj}<}>n7J6-NFwxEuM6?&Jfge+jA_^?&#v#aGPH{l(6wItKq zcQl*VcjxJVCur&uN9$h`xNVd_#!lG-jZJpUz0ifj-uB^%o@zXA9wWy7i=@6qok)(3 z<>DtVaO_(q?M?c#xGt1?yz^OXV9rNNKcF6w{Hf|B7C-W&@0K$6@tU+et594h+F<-u&U1hwzh`w*(y^` ziz~&nSHm$#vyj(C6K+_l({KA+c&_ikWRHCGFY@E7_7N=gX~)5O_S`ndm6pjR*c=hU zF}BvSyYhzoJ$wi+g*S`E6S6t}#Ap_~@0KO$JVo3!L#RFu=fA_**ztN02H&ng;d3|Y zIP21IraotRPlRh}EH!->V$gk8ZrIa})g!**q2+6_f6ht#^o&63&!Mb3P{92+vSB<- zomQ7hWd*zJc-~!^gW}>ixYr0Ye6*(T-$ZIvThn&eSXLS9cFFtnSom3xX>nxx0Zj$`-NWo^P~d(m2+rn*8rPO>bUOFiS0Khl16?^wHUzfYtj)hy_-j$ zTPDK!;RxEq=<;{GG5#J<#n1#}S&wP0Fj(WqL|a2{ldH$+N@I?yZIJPCG3J{F^G=`_ z{}vkKMA>fHubHXTwvNMIv;Uwm#e_!Ne~V$y?AY?>7Ib3A@RX`6a_%H@Sd3Ihr&;mV zMGab7q%q^O8Zv#e*jw&D4C*aCo+)zs>Uef-$l;(CKmM}U<4L`ACTm^6gXy{aaicFg z8-&rj<9@tPD`MycA8I%naOK$H)H$>e`k_}5?U6{u&U%2w6hoYQ+g z>dh?~XzEBW(`DGvf0amBby3tzQKHz`jqb%2NPLolvZf4bO#6WM6RfbQF`a!DC2*rd zPp;`L$9tzb@|8m~+8zIi7Y|~Pq52yYF%_74P>x#46++gKM`P7soYwSXTRB}kOMC{M zFf|@JuZr~Se5lr)fW3wu70)KKSC8?Wvu~QH_&W$?wvpV>rvtW{ufwKlLvG1Dp003j^AJZg8PrYOgm8xWhE^h zb_=FkKRw>Mn@F7}g5lS9qff{RVP`5}v89OCqsO3dKzrH`(dUMIefGRMn2U`1v3~pk z7_SK~T@mQPQG*yY2`hgW0FK70BatJ6f+ zP?q$n7muWRbLWmYUZ^g`#M-?`P8`gfTV7ln{t({vhp|FA5GvX>>|Zj13LdHKsAq$R zZ9MV2#F!rkK~$ZI=heOQWsgklu{c?SNA?x)zy0LUUhbSdFB*3<^JJ5zCSoE^z%+RP z{TACX?yMGVYC3bxl~PQec^||4+<5!xMmX1caKz;m*gf5gduCmN*_UzLx$**PyIS() z{bQ&p>&m0&x-esp3x|3yL6@aH@$GanuD?%0t(M?04OCnWSH3*?4egc~b42cFXtgMC@7vMzixYgIkm0@8(ut?+-l6XK zHcaxqkDV?~EGP-2ahQWpdOy(XuT=uiE>h&y^P{P+puthk)R5R^w$MCNhrgkj7;2Ki zSqWz_aA~N;e|3*yv_hKf>5I1X z-PQ!_>0buZsyH9p_xHfL6YsEkrXlAH zogvaX&49`>EzVqJ#+H9t{2M=t+1G+_qPR06FWHNP52GnJBakYw9XasM7BqNo#KP}d z*!9x`H@h7cW_8Luq&)zE=HBe5w+&C~^Y~O*k6Y*aF|;;^BTRpY?n+L)7?Q@;{cYH# zsTtV=;<(1~hS;`#BDIAfq2HYrX`ZZA?Ztxwidb@K9g0l*vDds#bP8(0rWf}S@J)m9 zm-op`3m>9Sp(7vtvBVLF5bErb*5cw(w7;<(y+SdPH^G`@C90n`b!{DbQ zU%!f!YHCmT`1NJ+7#S~o+J~Am>tOlp7f#LUP4#)5*>l?@{xY~Oy!&MEPaki%zPW*0 z3*yk&JPq~RHwuIIgW310G7Egly$dTAV#Wi3#|!gl&?mzCWQGqGf8B%hqV8O_@+0)0 z+(Lp|7y8%`yPU4#%ELGw*mfJoy?UZwH*(FjW}IE?Cz8b##D|A6)=>_=JB|6=>9fc< z@Db~4+S6s@2=P;48RW-yvo~E~|KX=FSnvj_hm06BsSYL= z=HY5^93Lr3_0sr~Os2FA*U#U?-qV3Jc&kc-@2Q;rF&FHR##hVSI77V~eWvS);cvsG zy)~GDi`w8tu>;?H8q8gJ%Tp=;2lC!2imY;HG)_{YYq%|f z*S2H8(sx)i`ZO|hgE9Nfapa$E$0c72X`*M&JFmO5a9^$1Zg3G(kAR8)uDirPAgFh?uJ;3Y$t~b2sL5kAp5p^i9Or9vQ6p{TE*y9$>hdbR4M3BRaPO*1uc|}nmbykZ$I~1dhfVo(R2`x|x8tv^h1@@BH?B0Ni$-{} zabFrk?E~=mVJj{wjOV*WD{*$%OmWWZ1KvE`4Cl@<=%fWM?lG9&dR=9u6IY7GZF=F% zdBK%OirB_-H|l)?II`NEn_OkI&-A9=`2i^P+mEZcTX4N|2oK%aidRK?T&DI)ym*sJ z=bI{cavvpkuydX3=hCJbFKtS&v+~ zd;fcU8ymzhxqiIyr4vqVxh=-plTI@nap3uRSBZGU ziG>RvV9MP#vh#b$tI=a9H{6M>3q4r5DwCVq7&0O%ktHUtp|~K1g^$~@;;sHxz>C%3G{ojL3A zF?9-V>uJ;O=nDidJ&5D0@5&AY$8(|VG|FOaY1x#@_M4=2<~=PUS7nRg0+aWv*+j`c1#WJLbu~3 z!maCQE+0;|o6wez8r!mq#OI&=GUKl=8(?IT&8>qZeXlTtn2Hud}zW9 z+s&Ay+*2IHf+MrwS=Ru?ZL9Ida4hFb+{omzjnwbABS+%c zo&$>ZTvftgDxhf`&8=Ujm866mScD`t< zZNgZ%XrZ_hX$ys9dbFP5k4hCMhtxQO{ihj6qbcVLp7DSrm3)2!!ik@@YYIC8{<-rga6e#nD*i#_@DoE01}!so4oUr*da{Vzo-bZv%BR10qU-M|w?BScmz^G4npbPAY>Z%5A}>7NqQlU?Xt zAC3L@8bpz#ZEbpO!9tZ*an#y@HpymmQ^>T4w}>G~?Ma9@rrH^KxhJ>LkUv<&*baObV} zOK|&BChHz|K;MfaF?CyGZ0EZ8f&J7?s2v3SNNeAJK^g-`Zl z%;0o}D&*0#MoHkVp+an&!frPhKNUu`gvCw5WUUqU>Y- zKj8k6GCr`0suRzU2Dw`)IQDu?^!U z>+*8-PaHU7Lg%%%>^sL@_HkT$KG$r^k2<|+(GP4N*n$?VSZb67aeLYpSS&TCXI2-E zd{_;)uP;%y)|5l%yv3u+vzULP1m|+(S*NlLF~&}8a)@Tu1xKC@jN-{g2hM9$V$R71 zWb_Zf&3S&T@(ZVMQ{nQLf3taoJPncK+e=TFy+C@y-S zi2u4MGjYX4`sFLp`F%ETJy?T@12y2^`T*6Bdh*0tT|S(A9Gd6ju;j)j{9ICpP~^ z|K(crG|`d$vK>REuwcB{^caJVSg^mHF^l9!iki2+=;&};)>_w(&HWcZ-oudBUN$1< z+7Nzg`HfMEs*?rjf!8V->M4U@Cq;Jtlg*{e}L=-GpLg7s@8+a?B(z%v8^3 z;5JE%Y#lA8Z8c~6;21WDDLB%&9Vh&2aR2Bs@o8iqbj;6U>A*0a&#Q*GdremRY7)P8 z9L%O&#+>GF%$<>sU2*Cz5|%Md$V7m~ihM z4sOt+L8&Tlq)bC-rzqAddC~pLZrofpj;SS4+`dv9N2(+ErNV`qw4?Y#|1E0foJL4k zch>v0WkH`rR*cz=(ja5JlX}kO$hl}p+J$gQbHYXo^&km6IM`uPFoPhq&So+Pf=79y-ynHm8p*8(keX|{X&88se{$|vBrBSQBDOHAe z!(mS^+8!FmqIZKRH*XvCxA}AEze&P%?|qEPYKLp;&%BH0l%v=-9JWKP*)HWC%vNP_ z_h1W54wgKz(7VWZIiBr5zJ_<_p~60|Mno;GMXwe1d}rE|2Hx|9@xGTbOA}50k+67` zO$+X{XwXY3ga?lI6=4S*+54lOq^0&ocjsYD{$4AL7IqWqYgb_JhMV~Ebh|LEoPvG@ zZb(|3z!kkBac^QgJdSsv>eDoykItvp=8I^FeI zAI9IarrwnxsI)nQyo(;(cCj53BGSBdeyZ`@&M{1Qa{)UyM@!e?4mS7qX2_FGV&5(^ z>UsH4ZoD-+UrmSB(|GQ0P~?RyFaAW8_v_3UI=9%sEmnok=GMWyatu|@H{tDnMfm*9 zlsBsKusS^y(<*8(s6LG%+YYanY(r_^ud?QJM;h4O5{1(JnYZRI^lWcI@8wXe@!llv zPUwsS2ckLP)-WUl7IOI6PE5X)!{c*3V81eo6)O!ye8w;?oiAfrxGU|{>Y);;%cAY( z$WeGM7AYm6@xn-~`IAdmwP9?`=*}H4vzfQho?9k9g4H}P_O}k@o3bky8Bxehr@CSI z@)eRO)t&>B^Lco&FTK9iW5j~aT?6uoyhgRQ8cUsB#p`r8 zcAfkk*0Ry;In|ji3c$fZ%M9C{?pWw_jOGYubPJ`bYZMe!4R1B7M!%mCvWK)x1`XkXR`VdmX zGP%22#=IpXp%v7YqoZrYKG)~)DZ3#vn3luje8G~Q5_Zjv74jc78QpmjFN`(u>SA62 z)eD7u@IghkQsU&#^89%-tyZ-4x`2ek&Wz8rhXri?C=(^+klAo0@wpgW`t zDUscIp=YQVD2v6!%QD_M--lh*%vk?)GEx`#az@@;SSW(ed5Z0iC1iWiUPUg8&BCuf*pWD*STxuIO@B;zcv=LhqHg=q;^1akMgBm_f4Yc5tvaFD+J`HT zE3d5z(#M!}RLNuhY zskser`hAj}4(h}t+s(ow`WBA3OkmB+M^G*3LLJ=?_}XCxwnyaCqBNH;Wz+Ge^{vdU zQx?lVx?tQL7x7|vKCQ!#plqPT|Fh=c=7{BZuqc-E>IQSV^ECMT?!vv>9YsxL9ApWf zupzgI^5vJ{9IHu_spB{#Q;t_sR)~8Ys&REdEWKMIdF1{iMox|<&pZ(iwhIh-X3e^? zb9g`KC2ow(l6tqq{dFG0AwL~^eC*k-W)f8|nsJZ&Y!p2oL+||=k_MoNONE>9yC#;o zo0Hi(aTvQtyh8Wr^~i7I#vP~3BtOoMv0dll`4>%zL;r)_zEaFSsmR8xcD&M1gZ&c~ znXWgA5uYY7akxB3oLVDtk|n=zk0HJ1_QqY82ATM{S43neiDgwWY(H!;`#%z_-~1KV z*Bn81q!)F5hqJPEHu_gqp?Gctoo)LvOlK6GYlrZSY8QSR@<*y|68<&r!+DPk*}*$p z(&O~G#y%ZQk{?rdcPVUC-ira_0(sxko*8>}SavcI^F<+5rn}MmwHl+=d!c!U61#UY zNAy((X5O0h!+_X(_;D?e^B*>2$6s|+-903xo~_1^ zi6cbC-DqjeCZp{fdCt$T#ixTd+}%Nra@{{;g-Q%}9xPy0ojNCP$>Ge*!QAF*!nl3^ z&^w_S)Ap~2VxyG1IhexYL!)VG?#|-zx>T9A2~nd~;8NL8u3Hovv$9cRd340_ahjFuGrnEO@F6-_}+6Y6FPUJ zl1m5v_~6Di9rxl^Tq1@(dnH0Ij^^6$NldKRgEy!8^QplF(SMN>|2u5PQ(IE_c}P3f zrw!v`-4pOulJt->+H5cB$3x-*s5LN-`Bx>4GJ7ZvbnHUKhyNk0{3x`S`f-E71FVQ2 z&3Ln(oKZ7`-JZBH_TVP3s1fQkztW2JM^yOK`aY(;t`hUQj^}vwMc8@Wk^Z4&*s82a zf7hL|DPv_+y?z|;)=1a*wJGme7IF8NuV^ZHh~_xS7yFaMgZUrDguMRr{T9n|Nv|6i z-;LjHEXHa2a?8|k9=T$|wcQ8uo4*ZDbMI|so>|wCD{eeQ|40=o zx&&d7QVwlhqj+}i1(6Uj8)iE~XuL0mKmN6saze_u*DPb=G*6m;w4{7clZcA+fZLP@ z2xxhQM+O~f{;Ut5uj|UqCG9!$k~{ykMl$-gB_|zvf^*wONIKP77@x9Y#T5&caT1M{t4vara8z{tHSs9kw|Pa7ZxU$gjwEBG4Xu> z0;ky{b*wQJ6MSfS{V&=*J0{!ntTRUxHzG*#UGHinFuH9wR*ja{RpA+4#hkK?$DKD2FYQwp;CVVu483!Q@Z)7CW(_+Cj2G-K z8;rdS%LuyHR$K%rmaN~FrZdx3J z?@!I>Bx%j63JLhTE{N$NYtXz}j{g;A%0^5I^`)B>swCCmX{@=V0kM{raCgR zB!xkTKB8yRL*e@!I58@MS`v;Av|224ITM9e&s`|Vai_|mr3f0|hW>91Y1mDjuU>nx z$TW?~lan}ZZzrZ^%ocrHOA%(>jQ4$CVf2%WVqvcxxVvc(wYMsB?AdH;+8R@{y)DSjmx)M)e)KdAN9Xa~ zC9lMQhZ-l~dCw+Tgk&@0kuK|!Q|Y+G0A*{Q6fso7EH_X*A)j}ab>sI5 za-3u0j>BhOBO@Y7Hut$bm9Cj^Zgd-7nqmQ~Z^z+u^b9N&?uhbsu6#B=K|Bnt6~p7x zDFznNA*Cm$skl+Q-(>_^+^Q7#8SED6b|1}^`@fqUt zoEg>-N1Kk5al1kXp2G%ljH3%|e>#g3<9zVh&7J*bs>;p}Pe)DVO!Qtj2?mD~#O((+ zp(z(H+zz#6&y9tA_9B+ut@nzZ6_Tbg{3a|yRk^$KZ5Zn6vH4*fiYiC&{glz{lh=tJ zhE6nJKZdV&5P zooeIv55te#!!pe+nD^o}{xtnV`^k#Td>iaN{o_&Cp1UQ+FPjbdoDMwwNy5a_o{4dI zD;s~oly#1cSURFNgM#j$Dg7Y^*nF4$a*bud)N-+l%FC`CRhN!#GdFhadi>(OvPND0*SbYs+?{pmh|#tumIShy8&kV%TGk4-GjG z`lr8OZFn%fkLmJjQa5gDlIPLEM@7e)%VO?7Z$>r_VBdfw#`o>Vx_k1B@EyU9!$J9R zanyg6DI7uup)x{6q?bjooxOyoKUCu7BRi;;%);u$f>#%Qg!f(x49|Uy^f!tyIvT)= zupBP31UqF(p68%IzB#-TC4WA6Utc#CML)}+zDH5OKa68_#`0jEF5QiD_##;1g|h~T z$@8+XyndI6*M1`=NZx4V@_5#DyNAqRWxfcQNY9}Q@w_ULk#Yu{I3|isA9Xoo+;sS@ zK8VmgZMfcHu}n8)8q%jkah#L`)w`HUZ4ZCZq}>w-hF6GtzZx;J+kGKdu@=tBCp}}9 z{=q!S83zv!qQVm#|aag3+>GAj19JmK6am4=q z{A*B#-xhU9Z*--_pR2Ia{f1wYix};v#@FvQ;fz+9P~5mcn9e4nCQ11;ojeRO-;W12 zx?VI`BD<4*QB1sSLAMz`_*LV|4?7<~gz7V}&0{>+o5oYKB`+%a0CJ4uko4PwQD1U7 zJNOO84m%>+4gQ1u^K>}iU9))7`wP0PRu&H$UHHl>89NV+ z;ZV6kuGuQ(I4_(O7o3*h&a36Z#~pmK>=X_-zChT*Cgdqe9(}XClyBD%AMWdO;GZr? zJ*UKVR&99L&VwG(9vE9~$rz^$qq=O2$?`n)>vcYG2Q6c@r-)1U83qEM@?&g-3eFkx0E=MQN`-%E8^FlGo% zj@eSr){lp|TugoapGdeXX(GMDWD|~0RjcGJH2P)9x%uAwZD7eRBfZ6YDPQpWTQ}}`s?O6tq(1PhS?pUlkUd{p z^W)H$-h<+k**jc~mYtVl?zS#G`)w26UKAo~k21TTh!zExa^W&+H0OLdu2MU<@>Y!t+1nxDoA(P57n$7G4DjOdAVMQB-2#TOzkZ z0aqI=hTrXUX3yFRHL0Hmb*>k)C2X{#DOt?u8_H|F$8u_PDzA>*gEr+x-2PKl=-9`h zK`$KtW|kpzU?A&ncoHWEApNN|d(o+mPr^l$~W7w{m zFQ)I1=2I%k0_}9VtY0XSqpWD`SA!9uR}j2jiQ(0m++_pIzFt6|QC{3~wg=oTqNy>& zmE~#yjNZ2uDpJ;Ap?3oftd28*?A88yw3Ltk`d$bU-_pz{;m zyk&H*c_!;~v>WxSNay30G<`M`>vkCOj{Gsv{@PA7k5?2PJBOo>|74u8UWc`|PV|+$ zw?aE_=(oQCIc*1Oy&uMPdpa6On;Pd=8I5e~$H`!?L^LT%j*{#MG zGiAPOG=aNzETW!dQ{BXnrA`lVUTh@$MD30-XawdC>7O+#LKlC-XkGhx>Dtl-bmsUy3CqmvQ*2J}1?F z#uGU;h8Ag}$BrSq;HHji(F){71>*tKiiAwCSOOEYLQdn`dJELwa#o+xI(t2<-K$!((7kRxcfq7Q2q%A>3KI6mm$$u?VLjC!s?rw2~-iV5Uu zJtI8-Zw!Bi&qT76hs;_e6RRJN!0pgXaplBPndN0a#uvKNZe}36FZhE^lV`(xd=8SX zn{xDxQEYzoN#-&&ie)(sP;fYnG?M^adgm+pOt^{JeYd0jcsUNa|3#oI94C?o@eW@c2r)zSgsXT99i{Z74GJf4XkvVg_a*53d)~SwX@I+(Ue!GWX5(dAk(gxqO zgE?X31spf&$Mxe~xW}s#D?WsX%*1$9?^4Bt!U;6*Dq+?`N5sr&-8i&T+NbB-SiZZP zs0;}dSvsXSIq;#(pgL1*G<_~>w_v)r{xvE0zEq#fY!~8f!5&;z)aNVbN}S1;@^r>` z5aKZswUUmLRI(8Mg$u;Ci`o3up(lT8{6*-=5bFIapjJgX^TtH5GFq1wVS-{<~f5j!Yai{j|5?a0@POXAA9Xt1vLzg@1;>z?w~3Tw$-u$h}%rpDmr!1!F%E5p5mi@nGjeC@$@X`i85}?&He=AKr?! z3&wMlQBPP)-s!qmvk|^jn{z%%9J`+hOXBSLA*c-X749^j*@Uydeqi2^C|oFShYvbZ zt$XrA+;gfG#ha&jt6$LIv&DKWiB{rco5^C)fDU|`c^2=ltQJ-Q<5{rCgZtHfV52mn zG%mYBX1S~nO>8Ex;8Gbr33;gW3*gW<*<93bJl-U}kri8eV!Fp(oWAuGk@ms#J3F2W zj}7I8lZ!;5t`mbUG^5NlN_MM<6Bc&x;r!QC2$5aJh;9*F)<=O`Z9ierB2RAj9Z!{; z`_OMxKh&7%^U`TEu9G;>z@JyJExm{>RzalXH)@q-@@-^;c-JqEzxO!f;|6u~$qnaZ z{~ai4cIJ`N8PGBGX17!$M*9q8@5Luz@yik$Hu$mMEO{bqKax_+c}>cKU9HxoeL^1F zmwF1LT3iseTszquf?1&Oo5 z;QOyt*2od`RWK&EhT`eswfO$V3K17OFeTcO53Rt0Jux(q1@lMt6!aN$9bq3^a5!f- zf_&t;;n7cMPFW<8%A&kk*i ze_>nuvD|$!0*>l;glk|ul&7!6nqE0_U0h;k@y(1>fp) z;NR1j>!Z6+X}}XC<)-4+st~ID2@77!_ z>vT&r)!f609%j^CJBIpO8sKi1kL;;?FtmOQ$Mub&?eXC^@IK`LHbI>5(v4!Ry!BhChLpvOqIiyXo( zCDxdlxfd_pHo&WJl9XSs5|w+R*xKa-rc8_Dn|Zl3UScilxK5iJrCiF6o~qDE-;XRy zY1SuGOXgwcju4$_h7?J9T*OX{yOBz1tc=Fh@_fA44+_mrco`gn1=8F}3+;J3+De25 zw;*+tDN}~`r(*3cvE=#=Y>VE5Eh&=!{Ysa2n<9DP_Y!y{4dRk{5An?36$AA1L|Q&U^I?~rDuZ^dw0ffltbJa}eVUpjBNik0W$=;NBjD)Y-Y*yRwae>S0` zQVVwe4iV8GeIfg=hyn9f!^5u-#(Nv)7r!A${-P5mnGaUcI5cU*-|D?nvZEG z&E!Xn#2oEBG3H1++V{<5zxy_vT{K?S@0 zmF{?OqZ$0yA}%gg=ImL|M2FUX+^CYrWd+WhGTNOPHm61I`$F2O%oc^ex>9sI1;3kt zw6nT`yG^bfI>}J<3UH)*lrQczev-2BTM&LIRF*2utnAP-Vuaynq}myXri}*NCi(6+ z)zW$Be^GSa;Z(m37*9%O5h=4$h?0ba^W3+QRYJ>%L{X@W5K@%1w1<}VplDC+^wVA{ z?WLhTl%n1Hy#IDx>gqV>d!FYWpL_B=JeV{UCGxY@+$$5eRQI7@ur0S4jAYC;Wt86t zVbb?aDE{>k3gg4DXj&`Uts8`aS$kofeNhy2l^XldDVX`E2cD*T(=JerI;~6KyuqFe z^p#kdV#T}apP{VMoc>Y8)J_fhoM9*W345o}{wB@TX(XQ+xewhAqT@0M-Y z9cYf1D~}@}Sr^wf{Dos#sp7#JSDB@K3H1e*BKol!^7gi1bB}N)?04YEMFzb2stF&j zbfC)#+0|}V4#k8vtTN8WmR32GQGHtOFBCyjONFL}4m{`nls)bi^vrO?(OlUrHZkDA znU9cbDYc#V#8;`){5RK|(Mx0K+AN&MKIV(%!PB78T#pw%265+c4_vlgiz%aW_&Cvr z%VmD`-5_Ff`)q1ucjV{x*Tv~~135ZSv=Xq@XjWPMlX*`jx_nc9ip+IHevnfrV*J&*^V1XBH_CoRr6vis`Y zqSIV((m)&DeUre4`9AEEeosUXP3Bj-j{GtAJ#u8u#nRA=**R|TP-rkKdlr1$U*Y+T z+o((Og_)Hfqhk+=t0fJn->%HXTQyJ~l*%LLwkV48-iph^%-}2gHm|}5bKTf0B6_qo zjjya1-UGs6Rx^=5$B>@V1Kii@2`Z(JI`!6mWI4IRu4f(2UWlM!gOlvx9D%Y^4;I|( zO4k$JiJ|3q)chc>-}2yJe+NEt&f%1A7WCY`6HfyjIqLdC3@Q64$~cPqpWYK8>&C$P z;e4zc+6+r&PPJm(L$Szwv^+OtbIPptRQ~z~;%y3&Q&xzX$DBE<_8Z#0R>9M;J5aEE zG%Nbb{=l}`_*&J94pQsNUTdV7_wNKgNcKR(P%}(bGn6ceOgJ^WC89RPbGp!w-IxP# zn0;1pw7D0$yP43@&Vze4+=Xi40PgtOmS*=>p?ORjI)u+wtcgm%w<|M|xW|(-Oxk1p z9I1ORY$l)WN-Rz5MD^K$^#2;g#FRi5YH5nU?+qC;cMyAxh@+NkH=e(!$EW8`;i!)< z76!M+INRQcx_%P_V`6!3W{SAKH2LNxVY|ta zX2I_ib5vBAU;I)i_j)VVzP^Wfakmto?<~Z*E`#~OVH#>nwql;iD4vSB2c6$L#Q3(8 zX=WS9OLro9q?ZEKR-<@(tp-)!Cel1zhyJ6p@p5SnPwjW&VbKoSog?9{SqYi z{f5=8Xx{Z6vb?&%;fMq0{ak}?@yB2i>ck(WgPF0~9qZh+I3dLue|ALieR)5A(<#84 zxh29iVw8nJx6Zi z$L(8^o8t-p@U@tlYr=<7?fEJuQCKtwZLdeN-C^0M`kKIjY3uN4Ri5y2KaMG`g1-9} zia#3#{r!4!U*109f1^F0w#ygxQipW=ITuCEcEPKQ9Y0SbG#CD-NUc&9C$HAS;8}Mr zPq)VpGjFbm+l8O2H$p?^VQq(P#ogK8FfZUMOdEoD_LUd6wK7A~r-ISb*5h`WH{B;J z6SG&TaKx`IFq1j48!fg8<8>2Z{Ol$cCBK5o@B|$1+zW%HHeqPkhqm=c0I6Bp1b4#e zN9RQEnVFd1(wGa5g<|yHf70v8fzL{rZdv0ed{1ps5$bd+!qXzN#0SI9s4~ zr5OVLEXJO*G9wt)jGqs!L64aoxuT#smkn^|_%V*`-&A&uXF0QYu{9q(doOe}#xv~s zXi=865Dx|oN2rKZ1Q-^I@5u{cw#$e7xfBt;r#@U)< z#hu~u`TIVKZ8YTjHP(SC-Z#ahK~FJCC5e+h2k~adT}a#Afgz98`1eFV+T6K-A!lA= zyKxMj&lyfbO&g|9yDT=kPDB;zaj)A1WYkKI$E+tp?R^Cfmi)q|LqD5Bgi<6iha7%>xkjwUz!OXD=db$2wuzssp zI928fW8&CnLmZyBx`%W7Lg;YvGmM9rP)mCjhM#ffh=4|nky&D|i>jD+)`4f=Xkx}! zC2pE?27Zo4^sVd8Z;fFzx^Je4EO{$(%RN|gya!!%=R%8U7J_(!)5N6W6*@317snpyGa zo>T@l^%Z+d1y@hXU~i2a_IqMX#hxgJEz)8`o;vOByHPdMj3?~&qkLaB+85aIec=^c zTI#6i<+u(E@dcBA}ai>H}Z2UsK&W83{;$%I&iziKUccT`)vZ)L*JL<`RAW{o@AM(khSUkp7q z5Y=55W757y==4IDC)$5d7~D9IHc1{xe;*^B^?ioYZ{0Y((|mNeQG!*=TJvHzbw$Ng zL+Poy@IcjdEE&?59?$;C4CxWP@8!!I;gU@;yhxnwJ&;@HD|5jhJ;rTyRunEA!}ZZd zv}>P5m(iD@ySE(=OOA?P{y(hFT7}<(A7Rk@#qiCKW@%^_?pu??Zu0IC5ZQ}Q#`lF% znDj|fj40gSGwRhQ)6Ytu zr>nC0uiaE}dU_$=jqk@NyJRnYhAxi$o`d%924d5`-7>#ygQBj|%S`UZvy#2LJSe)1A+867vZ_wlg0ZjD5fQF{-<*oF1ZcS8|>is(2d%97jbU86^(88h|x1|qRu{-r}8KA zzuhO1X|WIM<^Rdlc&eDLk;bg*0=%y>=7b0@8cu5KYFi-v(7#(ztNs&njb^}bbO19J zhKW7$`LjxLGOQ#^W3VM%%Nz{2?58%bx_fZfa8KT=Uko#6!6&i@pK`t*pH_s>QdODL zbVKCdZG?<8cP?)q&kIv#p~b2jIKEis3)M~vpKI%(l+l4|RdWz`W(W^lF=K6T6u(-S zGh4X`IU6Q(ZiiM>3;GW?8$JQ@{Q2j0OKv|G$8+ubO0RVo&m^l+NwPD%zt6^rZt~~L z2e2|>lK5CYlm{n_;9N;+8)f6jWjdx@dTBT2><{Fz`{STK^d@$56|VYZvmkOU;vN^^ z(4u(6jgh*)>|re2eGhYbj$wZP?y{?>Exo2CP~9f|3*}Ho|80uKhX%60zZ2Isj)bGf zNIrfU0sk#3yjnU86MGAUCTH@?htu$%q>l#47pke29@%;?{Ic)FIW^&~;j`4lzMYlW zQ*A-Bv4a?wYs0p?WOkrvG`3zV#;MnBX>-m%eD5`YuFbW0)UE<=qsOCg;d8u}ug^iJ zF|5wMhU;5nsq;gi|LOZkx$Fm{L3?oPw>B&ul`7htQR9t*=Ca?|2YFLpV`11*9LcT3 z!Q~&t3Akg(p{`WY>&=~Zy{WaR0pDqj1*VZKQ*Dcfb>@88HG+3~07VWJV(jydY}Vm8 z-pk&1m!RgH-osaVZ9#Zdn8fGfa_B!e4ec{hFkylkoI6O5rYx7W@0>Zsc7QAg?#96i zW0ZE(;x?soVz}&G*xmXr(#kmxwc!?OC2bmhJ0X@RQ7$IIfr_4*ZbM#pY{;`9OQz zPfNff1hU-Oh@Ss?@TYSyue9C(y)4O!+E$ADqkI|DVIn8)wZ&px9m&EN#RWSOIAi%< z@j6RBgQT`rnc<55m4fd&u7N|jKX<>_g!i47;Khbx$XJ}p{I`e2D)~B;FB{7hQmC^3Ky=eOFQ#YsGi%onwp?S!{xd;^pN>d4MfiM>x!}T5JgoeK!`%wR;^h~x zCfS3{t?dwWs0D*G?<1#`dCXGYpH^Jj*Pa_ZBwN!!gG+~OQ@owo7H$8W6@@>~i}o4=x#Qd#m@IE6 zdLBE4Akzur-?PIgmMkQHl?gIKF8J5-E1GFVP-}J&wdzJNrT1i-J026(k-ogtB!Rn( zf8kdC2wa_a5ivGH88hUYVobz$qzpCTkq6%~`+W`{#%MFq!kyRaE$C4&mVb^bczK02 z>gLN{L4Z1!zi7uHp8CjpoXVgB&TM*C2iMkHaNnT;^31MHi~Av*q|^qSKLV$^Xt2b% z0av0MP;TSOeb4NWvs(I@s$GzmxCWD7_v5ITnRtJz8ou8=cw?0XRLYj3`Onpuoz$Hr zshP+u(PhNDxiH%j&npdr2MRJI3s8+NecQtBl01{l4`tWwsuXhu$o`fV7rBn$zX8n@ zp=FLRY5Gy5kILY|X_v9lFoJHcx>L7F8m7*)=lod7Y>}O=^|$`uKaI95$qN%99#O23 zKGqU#Q_OL;fy4Jy-ke~@SKrfkz{Jb>{N1cHAVNFDu_Uj*chA%5R?)78k}NwxSHq9`dXueXcoWz8ul;P&h73=8Z#N zkb5?YYqicGrGHx%KZxhS6>qTQKqLHSE>n_c^4~7==Tp zV`Y|3vYBp7^$=yo55-1~g%`*;ocx*>b1+v-MkwMRH?T zOiJ1#tXJF>h7WFwC1v`2ckhb$V4Oq9+{&%!rd)ojv+NNKWY2$ZFx^dNQF3BY|1+Kc z8I2V#z7{mm--A%wER6h6g)bq+Xrey|1q5KT8HrTrXLIAPK(@`RpPC-x%3+w#DmZ4QJfbkCTou3XQ7X?fsq)cY(&iu zTXEaD5v|+!aGY-&m|2J8Pt8yCyKXJ2r8m*tCXLp*+1U8Rm7$VvyXt`S*QGW*sed>I zPLGA(ers0g*|1vr)-SZ$!^m} ztdP#Wyjk`{#KaaNY+{4V3od}QyRJBxp97cXQ-ts7wu(_tr$~-wl=$1f2V1IT(Q-l} zb;BdrWN|1H<5yt!)i@^qTMwsA9f(z37+CZkfg9f8u}XW|$GX!$b|LPkYICYdS6B=S z!9_nWs@|8`?{&Rc>K@Lhs-5C|_EwSM9l(1A*I=I$&)YTrQnORyOWTQb3w^I>wJ%$A zE{mW}$MO7DJQYLq=iu0kL9nqtixtOYZX(!CYJtsoA!Zv?{vA>TyT*wD@|<3M#19dk zrtBa&C8dqzf=hix+QEN zws&BD&UP5ods3rJlPafo;)(1Q-&lSTZLTOI$@?SFl_|k}<7ltxxPdJk@sw6W;GNap%;nrs#5qPNxtM4B}YPsy%mG!5G zZLOkiPFpU{RnX;dB(tU0U^zWkdRS{v*e;SPVyU8Gcms+<#tV_|M*V^jm=H9Pjn~7u zP}PimWp}IP@H|YE9ly74QsFV<9i}``@R+ryK`bg zCI?QvBeQ0``T6=07>=1BeQbAj$;%gg=Nr)c-x~ZLK8dq_*P-FrYg{f4W8!wrEt03lsl!CJ7ZK4R_%;c43i#sy-%FXhj{W< zn6%T6x^r`xi^y)F!ADnjpmBRD=iN>c1^d_H#FtYThHO3zxR3ClIq>Q*h8NtbV7lNJ z*m*FGmg(`4d>100b)e+mzN}fV>nJ^AY z;qxn}QPKhI-RS|YMy^NY=a+aY8J#y?)rg0>dend3gqsp9(B$_G+|rUhLH_|XdeM?W zQa@koZXxeIL)lR>!NbHete&FD4fA$GxiE}9CuH-wo8(}$Itm-f#E4(qiZ-3C_(ih~ z4sEw5kD2hv#>42mUl$i*hoQ<@oz}l}=%`tY{7QK*IW`o3iY_C4U>!K}HNGEEXUm7b zMZ+pfM#psKy0f#zXTKJFy|E_`7B=T@T`T(Q*s(CT921|8f>MBByNY#K`zIXH?c%8a zRA13Pt{v+R+p{(|20t#Wg6^){FkkP8{VU%i!0tIJT;}5M_!pvVQ9Bk(UCCwHFs_v> zsPj`I`EgD%7mt(o`p4sOa$pkpYbo;fZAPu#Z(OR<#!gSkO&J)-cAdIl;*w<9?OBGH zsz8jr^Gfz#Rk;1;Fshy$%`X=mQS95C&t}W4ahuLms!!pTM|M*E0X6a^VLd2n090zPE>pI#F$nv zo$&$_m9)j_m7Nja%AeUA-Jt*6n2wcea7}8>OTA>)|85eKc6W!vt(!2fc_Yk+cjB|% zmh2Lz$4rlCj+FPc!7hKGu5U%n9_5OYSL5kyv0rSMc35<(nS;>yIQks5<&6LCqWZ84 z0yqB@w=*lTA>b~iMOO;_C0TTvSAv@G<-)zc9f#H~L5)o$znJ!ATxce5UDf2$7s)7^ z_8y+zDNO1xQe0UvA1~T&#Fo$9@kTP`)t}6OU&ng-e4--)2Brsy zx9-EhZ3cY)^f1c9Mlf!)Jyjx=`6p%=c6JYBxPvRrjdUctaw@(%?m*1hG;Ry-g9l5x zvZnb1czqbmNnWz|++3NKv;X3t=>u$)IWXP+b#Q)fC#rG;mrp#80=uWklnjWlG6P0m zAIr?8GsOdI=}E_YhPUH#7^<0Yy0b5n*N)2_kgSmAjF26Jg}p7%dEh;4&(p`b;w|vFZ6z~7rrf_io^ET+ znNcMDujgSjwY`p&`+~&yV}j57t-@Q4N$h>56|J^cVUT+iZ!4r{Ue}4oOH6@&MW~Fm z;pA?{yx4LyG(9YZ&-4iHkhv4LpZ&SyPb{CFn#51?b8OTr8h>=JBjCS-cUJMcm)lh-s_B`5-cbe^d1NA+|`IITp+Z8}hL_yA_@s z5Uh6^!i?U-m||Lm8$-?5zbcl|(r4B?)q`HMuVb%zEDy*$eZi$1+LiQV^Do()({Ucs z`@F-j`Cc^LY0vYEwo7(G94od(VMOdy_?h>lvxa234mk+-sz+!&aV_*@S8nhtPp01X>fcbxiZ=B#m;~Nv06n7Kl^my#h>L^7rGb8f ztnCd<*(T2m8G`QHim~Q~3ztm1rD*9j1jSp%^LeO0f4|h_s6rEz1!PLzv>$V-Cqt|J zD_ZQHL?0i?c|EfNes->?eW$~E{UAQ~zKh4t9JoYwAaaKpGeFCY&Z&|&Gr$O?>z4z& z`*XQ>jwnh$ikVIA*{k%Ec){jWa_y{8iFRg%)J-f~R>5uTa9SigD|(umu*bY46hAZM zDMx2^3+~U{f1%8I(E-8c>8P%0&k3j2!F|D7%<8%ie=qweGWy%n`<*A>w7!B??H|eK ze;}RaoyUnadLnz>O$_P!RHWW85~}s7JXBkTve7++!8I@DE$_(2lo<$&e~I8G)3Ne_ zCky^tg{qHpaphQBn!Jv{HCMSSaX6MkU5$CxYz#d14x>kr0k#eJhs7Ud|0r<1}q^Z!p)D%Zk2C};IEHNdy2V;XWq4BvHhj$S|@lccH>!+dWWEU#Trou(% zJW{4j1qX%lR6nVGrVQrwcb(ZmrwO+|c`GIsAHq~co(S4zMH{Ivsa9WC+;ov=m+7@g zOMHj?j3F$$UyH7-fi#l^qD4vtn#<0)+qf~zkv)zodq+CfnQ*;cXO!4x)8}Ll#w18) zmRd8UO6Fnk&{rb!WO8%DYHXMXNZTVO(|pdV);LLH!a_VZ_nlT zuHi^-?bC)o>?HRrFPNh|x$xOK*kTc`J6&;uLEjMyuTv&PUYzKK}B z-44?nC*q;mUg*l)`ghAgaxWp9N?~K=j>Ugn;U*$pLYh2SLyQ410@c=or&!Q8H3w`HwFjsajv?so7tZ^B9JK? z#-a4&U@rDZ;0d{t@?JfMleYP>)wXVIB0snLny$fxY6rf(lENXWI^3~2lID`@cY8X8 z(SL(6Y|F!*Fk9vI*X zqq1c2v12Mf+6VAT;2W9C(B#mPo;c*_FE>@Bj&5Ma@gLfXq`{&5uWM%ttz}T$8w<5x z7m=G9p|CxY%VUAN(BiZ*zH98o>#a{Pc8n3ew}@uXHPO70x<}EW_ed_+ieY?tE>8!p z!~8ovv2pG;_|z1_Y|k-_ulSK@>_xTqv(Z&kjdOpGW_|8ek!@_r5v|&=P%`FrrO8d2jP_Wv z#h-`6WBDd9fC=(DK? z=e*H;PiaXat)JWu`6*@$_u<{#UWih*!Z}k*{F9ydZG(H@rSAl>GsXpm z-xlJoj2DJv>DM($MDTE zjy(&J%1b4V&|D=Lt`SPj`q|>L z-)k4H5PWJk4Of(Z!0?tattHF);JZLnMyWEYOA0KSOIEqerkz#n5x1&4@aQs`ojhQ` zPm9XY|CJofOfAR7^5LBETFU5OJ2RtMHM+(J^Vh2q zTwWf?;Map#Ik>I-w_c#fId2|!9>xppI^+77>4+cQ9b+%1(r4BP$dXciiRkOLgcjfnyOu}5gwE|zrTtV^fbwW2$_OiWgdH=&X%*~AD*!m)ZR8Z^4|3Z%yf3ZWP=vW+#ZC7&9;cu4HbAZ?y=}T?h&qh z^T(BTJF!hIR`LdN#NGq?cqKh3o5n*B4w-!35Go4oWBBRZJhau$r0e-FsMeC39#3)= zzklYTvxO=T8Ro+D`~R6>X|+4b^+fp;+*sw$4>jAc%GFY4 ztn9e`t0nbPI>5YdcSgjt6bFSPHeHsP@e)TGI;|4BdxbLn{AlReuf?sNNo-j!ne$~e z;)u-eU$su-sK4oqP;SL-Dk~(rUlq#24aWy9LE}|*J{z|h`3?Q)^;R9Gbw)fLHk#ju z|3Yv@A-ZOT(e}U=XpM>B+(RAEV4%XXKdMZs@!_5yDcdrIv<{GK#*AHitdz?BW9~mTic2$mke2K+g*_|?kR@rw3phF zslp~ch^Km#DE`|LDR;Fj#I1+xky|A1mP#rdu*;Vh{kNka{~iW+?8+nlgSj2^@isX3h0mm6ogYq0ib96MT-W6^ubC%SIV$HxWrrI%$q$c<^Qr7yj+ z3lD9{rp^UV#r%^CV7D`c^CpeJ)>0p8ee~l@r{Q!{*A_-bCj9HlFs@kNv z+HSUnh3!Jcg!wOFcQcn3Z<_N+xdz%soAacp)N@{`z|>L=4dy@a^MeUH>@(rz?3Os4 zlERHeb@-+)xu~gX%>87=pbot_aoj_xx%Xv3u9jrJt%gd=f#lE0+%(gXcRx4f?JI`d zJXM4B*(hgY0KZcD&3)D_b3R2{_^-Hks*QWr!2Ud9_9LUSAG! zR!0Ao=}a)1h1d5x@rwFOoRm4o^S74a@+Ey7Ham-j8rFPv;2pMnd>~#WH0L^t{#5Cb z#Zf!E<8z;S$<)c@?}+hiTJiy0_XCZ2g|I4}$Z28bOjw{z?Zy_0Hg&7v)D=2AvA!p#5dy{u)&w7I?$(sV^UneJqBK-h|aI(cEfq z1*a#C;dhNVcBN!=mY;*$fz9w-RW6zxsuAAf-B=OOj`fDgJnWl-;y>jw>mScG$Iqij zfHm>q3F6?z5$9Hl!=LU6!(MlA(mR_khW6pD?UT8@)`iE;X^S`Aby;vOj$7oJ+_Fa& zt|=vR3JU!yYb({4VbTEs_p;EiN zy#{KzeI>thARMe7piuHMV<>gY#!lE(GmJgcm*MdEg^K&TG(>K%^B8eQX51>CiEb4G zm{~BMA>W_4_HV4j>sr|{FN+ilT9PLUpTY02WEA}UhMJ!`l9_DC2D9dD*Ca-=Ec+1V z^HJB>8C$hlQ^&tIi+%KII8g5W%z7r&-VA4pdD_f%Qt;AU`5BtqD0T4@cyVVcR1R!{ z*|`+z9gE`2aV6**wOrBR$4Fe8Hxto|O*ow|hr2aIXAazN}KXy*Z>fQ*FgHV^5>p zp$cCgUd5jW5!l(Z8F#F%gJ;Qa@pa%$;qYTC2HcuJr-8+C=V>oC+l4bvX6W9}T`4>t zXYfgkWU^JB6{oH4BXm?t$@6#NjCm(Sp=&W3oc4-K-Bpm!3v~=LImXdj>ZZ2MD%f7nSPb_#Uwd49BRLDn0V1fSFA6iV|&?aH;V6CbYso*bvU_Gk18pqC+aBesU*Rfq#@n8g%zdQ1B&mH(r z=EaRX)X_UXlZEX|pcFHP&)#L@M{qCHOmOGx*CzCQV#KM2iL8pPcD0||ha06g^*}3$ zN2D*fs$emmR9+JrQt!H#Rf=z?<#}Z4D@B(zD{-}Db1umS&+e$ft(~J4V>ToZecJKs ztqSz6+$dV#kHJj)PvXk^4xBCh{eD|+h*?`AxN*5VO`bRB;M$@1Ff5Wa(O0m3V0X5j zAH~oCt?Ain7|lvUIahs#XuYHZzuDZtI=40G&|@JsrSwDIdf9hqF__kKeb{&FB6yvN z!+^!|wd&WCll`pGRrLn?SPbIoIpgFr#sEd#WM5z2 z!t;pM^n0SsYY|PU9HztJ-&I(2)Rm57BwxOlKE{9hj2qe)(Is(%@Eb1q+3S1p+0>qj z&FvPT*O6YLy5y7a2z`RJlD~YnYA`3%juY847GuggGfwEQ&(Z7tqPxB1NPLiNg$hG1 zi#d+X+t1*ZeE@p8S1bO!=|GL({UYUTl(6s~&o-Xz_$zZ3PMXRdTP5izS%`6C>tQ{i zQg(Ia=Se$(<%47SLn)pew^w6)n+R@^{pH=m0%3b|4o2-(=ai#@c8l)AdqTY!?)n$| z&pDu!$WN=Sf zte9KYmaosQ6;Bs=a7;`eejM{soY+6x<>`AL*2NpKu;mH(&)tB}AGgAM>mGcH4`k4n z9+U&9yk@4sH6|&n`t8lY@q2N!T#wHkHMwi!C)ji}W%@U{Ju`eW247R*=n!8jpD?6; zNF_Q4cj5=hjLz*mh>fzRe$??P`gQl?P{-XEI#Twy{>qNfE>}*d?9JWX{kc`XPbYS4 z$)263qegENl1l5~vsF!Ov)!neV&jji`O4BvX3&PIQ)MrOEQ{?mE5|u{@hM z{P$q5dl$ZmwBTzi4f;G##m!BRF!F@D7&FV71#`M#QKKi%bu#C%VQMVCqr$Vs|HKl# z5RB5%;KjBwtJ}w&C)TaNWqQ){sH*rrU+(U$ZwbFUPJFqw59e(PWwZTXVF^{ab1@Gi zZ~TErVmpr7;sZLlam#~_RKGEbO~1Hv(hW`S9Wa5z(ic_@h-i534mI_*HL4%#{7~ zUg^AkdpT0KJ%je%TS)kw#ZvuOsNMBU?iDY9m-#&GsvWBs_cEFTCN73shSd0nSqPtK zD^A@zRZNz;L#MZbn)*`&T7H53u-7sdP#~G7PFOrYfXxo2(^k6>>nC5v_7)ehH(`qS z6`;>a=S=XpN`>BKItmBvnPS7SG+rxc!W2*Gt2&tC_MhI|e77&ZZ@-JyCL1wt^kgHZ(*ph7IRZO;`Oru*sh4<%ZqPO_oYpSPTyOSH{F7(9W!vo-!)S&Cwq?wpBS>8SRiV~!9Luj;^Jr;Xbg0z9TFD1`cF9wA z>xQC@%;_GuJ_{=8ldRklXa2oC4P+0Q z8cV=Vd*$%q7=kAg@JQv=OUFt2Hs-PGtwd{A>uy$XV%;~8zz57RW{1?F$k}02+ zAA>$C_akwX9@jL{z9q8FcdG8xu z!=$zmYgB>CyDfNujUsoD2}4w~m>@OVZVl_O>2Wm2gvxtz{(8I{03;34=FK_lP(JCk z%v3&9eBEronN$B^dHi60N$kn{GPC?u$o~NFJhF%IC z8vfu?m@cPWOoC3&GUVjU5XRAth;r-8whD8mug|5dIq-MZSM-zp(f-3nF@1q1v+Mnt zcI6=c*#@BV_<4A8c@Q?Xsz$dnpRlat06xUn@u9l69>K*Ic&#E11EE}V-NmoIgu9(OK?Ur3HCkAkyGA{b9FSS*KashWp7dJ zoc>w#8zA>MV!tB#ovZXs#&YOJ9c-@a&s`6#m?}H)^BMy1`?LiVR+>Eh$%NfxPJ7tp zVD_{*h_AX|k@Fyx{U;BRTLJTN<+T%&KN<_&#tZq(%X z_MNeDMHeP78O?&4J-DixNLR@~TOzj;UO%y8y<{W3JsZzS$uj%eAr5yo%5zzs+`!O` zX48c6a)aSA>Oab?z)OAV4t%BP6?FqeS~k=Qi=yS9U^+i-#9=wYqf?d4()I3mb1akx zA{;m;FO$^NLj4?-4)wJc;O(&8wmw z@3Zqnlxqt5tGID(jFQ}bc4F|FFm?&;&hv9Jd1Gc2!&|-(HAf^%{H+F$mdg#?ZJx{w z9>(smpO8MM8C~T4G0|5I#{#0c;>KB|6}Q80n=$MzSud{t{=#5PGfu8t4*#`gG%gC{ z`S)JJTIR{ycFtkj$PV!KX~2}blUS`O3-Zh2FyUYs9767kczvmN1h~=h=|Rle(vl9n zmSWS9Z+Cu-MkRuq+~Fv(~lx9ZAHPoh7kPpuN2S}E9i;Z?=5+(_ydKT%vw z&!mU(4ypI2V%y9>wlVpG>*s>lQL=O{=b3Y5zlY*$%L7>T&x`Ies>HpUvNzM+n^Pwg zAi&}iPTVyR-7$g%NzXe?In$LEN)93VE3s{L_1m&~$B3)Ev^`@ws)FQQn=^8G(Em=fsMeeOSE1 zk-sO|(0lzP9`{S*ik#+bu~P0O_uUD@3=g)l)nN;{3%5LPj8NWw8?QHap?hUJT2kic z^sk9NO%IEqmU%*LW($lyW`bU~C5Q8~8;``vpEU|bg56MFzt)sG<^^aXyZ`-vTeD-& zENH)!PRlp^p!}VH$|BFGmU+#Lu4jp0*}53;mzfi{7-)g4$Sc7 zwK)a|YoE$`6@SDJEf$$QcL7JHKy2%XnLV=D^x)Re;)6*acA)y!U6HFfj@ib7 zjb~q={)^mbDH$!#JpF}Yi#^XyN#TGIQd6zms)#pJmP|g$h`ua!{2l$+*IFMfXH_6? zcN{&X$1BPr`O7X5<_m|2ir!Jo2w#l5p8avG+cdm#Z^@`+$+a;mlIt|>7&6C)6GRdk zM~vjd$BU6t(17<^OW`xB0;$by`Rq+5r&TtUIjh+)oMbHhh|$cG&*GVj=Hj;1Cd_|# z7jGQ<^M>rix2{=+$CW#9}o91=(x(c5N`~ zEG#%CY$jg*7|CODJEq=Da&}A$#l+YBFgWvq=zOvTR#@%9Y`J-;^!YdnrVpX<(*)6Z zl@_uNYQx#llKs?G#g*}oWe({LN;-Dpy}$!#j5n8z&75BJ#2g z?fTt8#Fs?eEt(9n`XLfMfm zqlk>`9YR)CR_NFxNw#EVWR>6j`}>@e^ZMrV{XEZoU)TF>fln*zscNngX=P<&#g1|8 z2M{H%UPeU*)%#_T{-<}GFXC(rpTZ&Ljoiw{j3so%gv zyi`?#l2QRq4Yor7&$X1)pGsyb_C|k=B+BLA&xZcW6nk=xWd1h7+mZFOhqIbi=QEt! zN>Z?>$9uX|8Hgiq{))ARCnzDc7mAYaQrqVa+G*BK2lr~A_ER_RIUS%ymrN(zaX9d&d?s<(yMP2Xo*DYoP696}=cBXw2iDh`!kq@Bh?MYFB+2 z{GEgi>o(BzZTl(JG!$zV-K2|hvADHP3o38&No$7-#=o}5yLJy$o$rTxiOrOwJ0903 zN1>3<{ci)p=-K8l@hD^f%IxP!q+-%(iB%cp>EELv&v%p3oMYtHeK7A(^=Ztjzmyf~ zh32iP+30OQ<78oRx|6zmT}n33{P3p* zNOMg^hp{D&kvA5F_rjEQN_4%lN*v)i=W%wqXYl>^K-_u?;n~pim(#J)HxWxWd?7`B zo}J9FLEM=8PHtc3t!Z~+J$FOg`vA;|TxLZSNpA%uV%77wox6rpU ztBCV!YG63dfO?WMx=#2Yl^xH_}DYUsGG9|jFnz-HOq)X%S% z*zRzfMm}R-5%-~dr6!ZaWsfkw%wFc&Ybt zQby3=sR39L%y-r+DJZ2VeAG5QNX{Yz-PUnjLp?u!NkbwnIb!NQUNsB=cN!si`5c(s8l zPRfzbI#aqfvOi|jF;C-z14hbNbB1C+Mb&o4IWW8NTqkLIyTkdc7A^aBg8o?cht}!A z*m8n%IfLSGZM*`CuJE~P>~^aCFpiyT=O{&bn@h`U?jkcoqI<6=LSOwCJ(3r!JUtG31`UB5f5uBk zB_nICNe2L(LT8jpPieKAOVD(-f! zr40ib#k0zplI)R6VzTu#8a7e}UFUh?VGhqFkH}-d&2mxJ(}njIt+b_!0R+zv69=2p zv5Z*Q$t2L8!Fue0<1rNZA!6D>vD!o(k<$j@!JB!c%U#PoyRS*KcWR4{Yp-Z?<7HA> z#Jde53^DI2+9*URWil{l-ODs7*9%dIO(71cA zT<*Lsr+L$#(4d9RH1lmQe6sjQi+Uu}Yr{YE<>Wtdvpp$#GW*|trVaM=w!zPnZQtpx%t4+deGtJv4XC(aZcaJ0!^p7At0ua=7cngoHs7$5mrPaclf}3 z_;6f%G8FbP?AD$O-fa%WWoDl5UzLM-TFa^)jKI@_$AqmbZEeSw^B;q(;u3=E!Lcf%BmrqAyfhjsTdw)6YF|FsB z*1mR4c-}KY>Eqp^pYD3vZ~jwU>0vKD;>5tCTE2;=Wcu$FN2qJE0<;zxO;o(0!g~HAa|G z?N2i_D~Hn>&H%_v&q0r_8MrXuJN-&5B}ZF7{Ql=lveQ(c*PxBmKNc9RZVT_z1F1Z3 z8l5zbM)o6imuMuzEQg;9W;1DwZKn;RCcx&&8i}?2LfSn$5Sz3!u>Q^fb_i?Zn4=W> z9d+T{u7l(z=h+@8>R`pPzY_gHPU4F?cX7XHl0`r6n_aZWiJr{YYKlYz=MbJ&L{P7) zRG3USN>V5c$kKDvY>q(5xglJyX%*U`ECze{ax=ZsSTD# z`oWJByfu@&ZJ9SwTu#Hs4klyXuP8lvEqb|5KksL5(PwhP=l<-`weR~>Q4cyWA_?2iqbdCn^xk2IVmADvqh)nB7VBM$H6wdko z=82~4v?(L=%qkkZ(+aV%t>Ti=Y^t4*g*)++5jlAYomuBaO)9$3Z!(49^ZX%=eh=vK z@zYd(>N^E+Cun=`4RpKPByygehkt{oBgXM0tr$9%rXROQUs@+315EMYbtD=%M>EUz zFLh>^@!8aZTy9K;beu6}%8e0s$O=a^Ea+<50`X2S164z8(c-k1b~#1Sx9z%O_bFX0 zky}ZtJNcRarHi!*mnqzD7|L}NvHSW2di0DtjvktL*CF7l$?Qijc7}G2LCW9mk{hc( z)2E^ONZ|XJs#9-aw;>ZkZYpNK44~H${ZQDFLkD{Kz-B?AFuTX>HcR%gOyFnuLOyP3 zj}ZHB*(1Mr9A=(!LT(OsE}puRa_SbEFZ+(-m#{69}Y zZl5>wDQOJ#UuQy2D;g+q+z|L|>Wj`qQ@W#=fz9K}>6NMvcjb0aY~=y*z~eCm?9RX& z-jRjs`)M2O49iwh}!1${tGC9+_jk8v#hL1$Lj5Ktf52M5La`EU|5M|n2 za%tP6h_WYs7|(sx>@%J;x7$m4UvEJ={pAJUNr*^mgBG$u+ z-??2eywXN|I}{K9=@nwz{T-s_Qhz+Z>p~@GpVKq$pzo^KL9gT{aMold)xI;sL%%fA zyQxFg+qxk&O@ea=Mxwig4DDUf6Nl^?g!$fnn3XS!R_VF)CAW!GUvH%mvm0rv(-gQF zIiO7a5p{(Bq^cq_W>uPC<)?FWIw~3Ix&hE%s|9_zD(2Y!6wk(3qTrDnsaf*uyi*-f z%>7)H|Bv3r-xphS+L&{|_n21B=AAIcy#5_j`$PvjPB+lYntXbqI>cq9j6Pf^XQ1yc zX)5T~AkhfBz@6vO&~{}H#T4)TVSd<-TGPe-y}Jk@-=EM~Rb6{Cj7<2!fgrY)RA zMd5QOxXv7Z)rcWL?Wdbn;_!5KZZF?#RNT9i7fMtpIgME=Yo7V z`g+0sv?sl&ydYLQS}Jzl8;em3EwDj$JkD$<5wn57O)>gbod&P6w>0woXYqQf0)2hh z4`;n%vEEDuYhGyK<@<~DeQFhHT=T@$qhTmuKHcz4Lln6mN2tW8xj660G_pCUFJw6*Y zDZgn+vqq4VR1T^}M4?;VMfw$2$meHeTAA>k4jz@pvH))=RO{l~+dy0$Fd3!Z>{BFn z1eJ#4d*@8jiRRo-q8-`L3>teS8OHg{Q+8IOjSAPOSk@l>H7!WixF_dhN@>`udWsy! zcVTHG=xmc>9=|QkOyqa&y$l2&?ShlDxFdSRfTmsZ#~R(^RQ$U{+*|sO)>MC|u#6G3 z-Ise$iv#%#;ZG5pb_v&x)1-ZHB*`9}MjsRTY*)334*M)1XO}?g^O#+6KRsyC;-8c| zhMkiihT;52=G_*k)4!gN$ZP0C4DQRFwALten5x0%Nn@yacm~Gx6E`FD-AGLoLdu#JbQS^tjRt8oUQLfAEc@7XB1_ z-|^24x=fe$troYw4#II}ipTBp;7;5uG8A5T>i0+Ddns2ma}VfsT?W0q^ih0F4q~_J zSXk)ZCx_U4>L!d3^F0oUB?rX|zO!xfoQ^^_OYU8tpn#HP;(WRjUSB#(SI)d4hc$mm z^6sn6Vm+QgQN*;@IgK#U6`v9Mhldt&!&NfFNYVRlnm-u3}S0_a%x}l29jb zF6{~}t;5XRV*W|1F^WU{aJaufOI9sqY&;_Z3L}_#ai9K0^&!^@w<$lKXY$21)cb87 z&UR0N$<~pGTb@NV${$2mt60cg4sZ#+-#~J`*qbCX5NB^BVf=sVBtGK>)n@LetBW}U zpc2EZ=tK00KjSN*rOsY{K>-e+mln1%F+cArMIF=f( zCEN8)^pVu?i}S)e$2O7tRCe!%|Ca2SoPxHVQ}NY7nT-82ahjQQI+gm^lYB+!FPnhO z4i^}#-Yy34&;6PmEE#x}Jt&%6XwxW7I9T_DY(--J>K#{oJ|>kziU_1f<4M)zMQ|$rX^#h(|Qr(R7@TPq4d#k zr{uiS1T6f;-xpG~G&GL8E-5LHDO*lgd-3j|oxkJU{Lvv>Oouvh@n_{NlKmu0x3l+< zaZKAJ9FdZGo=X2M-2zl_58WnjS6*C1^FBQd)gPUl}B<6j-{Xw6sAJCkq zf5@w5IA+gx!>X_{`s%iY&b*z78+TNBMs%J`P4da%@*uoq=G&*s&*+(j3eIQqtn79s z)*qdM^P{ZD-+(Y@P!!r~4Y1^?4ANi!B#i)n`Vel8s*F-HI>$4C>3`_{ZF!7rQefBI z8G6F!H~+0syjPzJDFthMm-)%8UY?s8cEhzZ*_h$tN()zVcJ`GC;&lVrd7+P&WlO}0 zpVgw^C41gZYGBUybm0;6h3-pB@VYRFmM&Jsf`y!2&+dx<^mQQP>WkX%+Q{a=-ztLx zadXILadCUBI2k&c28HgW$K!G^_%r*wy2xPt*X!iBy$jNexkoXi3&Q(HK>cFAIJh?i zeRY1YYrT`k<@uAd4F626a};%I5#9XJ2a3GkP)_MX&K}C5;ZqvYOEjqB%5qvk6^LGEA4=E?z*6o%)y_sDi}j;RxR4g~M`Vu{J9f(+bj|8nuWf zZEB!*6UXD%x=l2C$5El##vQ7h%aW>|&QMhk6z?`q!H}{A6x3jirvvOTK4B`_oB~n! z>IHS)8AbySI+7Y^_P>z=ZvFMc^1Vv*N%;`%P=7A^4>>F<&R9`O{uZ(Jh&9dJIm;z= z>N1y`@79RA_;G{NE|ybOiZqn%f}xW6P<*+khM4n~+#9e z{P+Xpp5X{fm9DsS%o6Lb+M;K_fuMaBSlZD8Zykoy%EGSn^NPLLtM^hgcOQr>*{}?J(tkmcWp0l6 zvaCPVpHM;yKi>&y*JxqZ5Jdj$jfNxq9kfE5{dw(@ed&*AxmGbd?EBElPo8M_X$!Ca z&d@By1m^u0plnti-%+?*{NGpl9sGoRUqzrF^FuV+XTblw57Z{ukoVS&;+57YY|meyy_MXT^9w`VK52OS^uyjfElH!XA_|?%;GaGX>*w2XmaJV^JiADqJf{s# zG=;6q04$$!jAmP?V$J*ha6RRK>KGd=w=Jd0qGI|fnDZZXonA~#!V5E=jnmtKqIb6p zBkv?=Ot1B6PP{JwGR=Omu0;3!5c(!B}89B@G zOs1S{19s4quKt{VtRtKHF*uyv4U%+gXjaJ~ZLSA0RM<5((*hF}@@c)cJ?KoyZH*m$%nTugkSs9Y^s zTP)2vT@}oZ3PHaQifA6Ay1<;M~h2-T&lD3fGNf5ImSGiID zp6ou|RzqIp*Qg~lo1Az*miR;g!P=|HD&aUicdw#526@cF`%3x`|B=1HNbKLO1>Y|^ zXy#tI;cgdXm%740pR-}zl*EuL(VSUoAhj_D;?m-a^!}DN-Q8=A=-%w)jZzS&?(^Au z|1G+jJq6Dt+%LMAif-@R(PLT~PUP8B7<=n7yV=0;w7PI>pF?vRu29sgdM2|=QAVOY?J=X?rhE_M-t(+$S+w$8I;xwa(cY** z%AFf2c9kxiuI{84|6Ym{TMbD6SAQ7Qq{H`zJkG-ivt~L%^Jg;lboR#Sv|m(Ku8e)X zM`3YC0_OOpLFu_Hbd2&Kef1O#T9*ph?R&^Oz@MK_cBdTlhefU;4mmeTMuzsLwAULb zK5ZG{hzT=}3Q)AZ7rJ)6M>UP(V4M?*&cOlrJg=6L&0?sUGZR+d`q99TH)t?3bqf6W z9(p>>q}SAQrYD+(ffhqxa~AlE|7r_@06O)7-NDX zb3W{{Fvcd9LV~7Zb&WMPZI{po*$4FBx_nV8F9!>Dj;z`fM9ZIkqs|AX$+h(>D=~tF*>{n| zfB#BM2II{e?$JSgjhK+ghX16_B&p_%0p_||C9XCo`J-r|K5c3Oy-F<(TP z7*c#r548H-q;)qE(c?rvQZnC0YWy6XY=0^a`ncdsqdf9nsMGxJzbT6SED9?p;LV2v zq&?RJVHNgRz3CuL;{CE`YZE(f~>I<}nLU!A7{g9#Ya_YsAyiG}lCXMB9M zn6m5V2$#xu{FKkYj%jL0mNSR5j}h7%_|J}w#-y)WB68nfs{c`d!cms!oA8ddEFVL5 zqDmNia^wCOdv+>h@li-&i@g#u7MP2KKjk9AGzC$~el+Xb1^QRvjsCk;aCQ3-dN}eL z$C&hjbdG0O`zbX~HDCWG@(?Zd+ksSlN>;Sl* zMD+z}GJ;;YRUsRttNplSvC3#m|p~3s4t@|_JiQ%~a`UPEkIuS-as@P}MMB!1sGtLcxTil2J-UsD#z8|7s*sIIRrf?u<{~P#xlQdy9*}wu zekX?V?_i$Jow2YrIQt6^wx(orC%_f?ool? z>2Xlw^MF#J7VYoXC~STVK$6iASe3B{z_|}r+PGos+$6+*HNd6DI-z>!vG}Py4J+RN zq{xpZ_agOEk`H|w6kvAsT8$gEVC(FN|q&khm^!LmQGBjYG4d2iKa@K681>M7N?BOtEZe<=_p&DmL zd*allN>VDGMU8>k$mIKOZpcRJQFX^<+^-?nx^k}A#hu+L%|Yb-IRhTQ8)8jrvk*V2_)-{ZxJ?6J0<*S_FE1Qf{3!jMTCHiPe&_H%< zSD|$vUex^NJkx@CB+cEgpL{lY>uP}KVW!x1Vjv<__Rx5{Nxai=;EdZWu|x48^J6da z!u%I)>X8diUnkUmd{QMfD_AO#OD0V%8iKPD+MY?n)@V|C)ljb54w% zZrTUKX(jJMc0ck!bI>Godt*w;TTEd-C5GA`zo13g*C^HFrm*QZ6fw?iRLeQ(saw*Z zCY#T5>LmKN=D2teJd=7X>LB?f<|rJKW}oLcI>Mc7^M`BcaktMDut6FZKHrrLSe=a@ zoV_?!7sAg+dCS>vDpX3WX_QVEgXm_J_Bh)jev2gMolU5Qr7Uj`Y-qUL>>jACJ zM(}zxfNX0!>9$<}!kv{#GRp$`cS~ty!7*VLIt?pix!|`l)Ppr?4!e%e<=mV8q#XfBsn*2F-<<@kFT8PuQwPCt(&Sm&t}%fw~@R9T|q0RD8Rz^ z2^Cn#pvPQedg!u&q{ho&e5WExyxvS5N$Pp>P1Zws zjxo|naaQ#P zjqTqHCqu)KFtUZVtGi3?JualYF@s@}yHO~OBlZ$>a563)S75?>Al~`Bct!RS&ct)} z&sM34evJD;C)-A%(8>%(LMw`&vtPi33}++8uMJTHd_v{*R#-~;{ivhKU9~# zfi&!c@NY{2Es_Q5@8+ULMjidd7da zoEu61-F3j=(XkkFpa&d+h>CVuF$XjpH4W^YX)O|)HB5*- z!VIw$?W$)T;2gR?tV(4(+Y5-ppKl3+)+~aA6bv7B-1y%AC;QQJ|%1Pz3GRTM~ZNH z{Eb%mH&b<761!}q`8{=+?q1Hv5pQce52>T|ZtS{~Pr{lfk0{F55+5RNkd;pZ(Wf+t_dp5tK=On^&S)xq=)5IaxZ4e@<+n;|W4q9(z&KQ}Tdz|t8mgyy z;OOlE^i^I5U3=qy}y#$1xLdrq4y1^^sjv zZT`$Z8iQq0PH22Vyh~?pY@Zl7xP{Qlrpef3^@Ro;<2hVx45T)jV4s^FjjX>zk>ReQ zZ<{^#*msh`ghtwa%?BOfBcN{mPtrT+CZ+dgANo6YI+iEF$Ebn07syTqT@`r$Od-kQ zD?;suBc=zJiuNv>>E+m13Y2P;G@S2+O4pk%exI$dckX{yeh3%=}i{K&h`VmatIb&4f_gQ@$a_0%}wym&rtllb_(x!XqZG4vFPla-=pNg>JXT}}O(D(UkN zZ5(coCB-?+;4F8+_Rprsy6lgvjYp^@I0PmbnFEA1xt0@r=az-!@6`?49BwGSSuzY z>uV;`Uc1uI$L#Y+am4Qu_I#f!fMT8=?g?8QSeS%y5nh;;DUH7smI&ElkAt%`Da+^p z2l(BbuZ!!?m z>4f}2SIFXV1O4W^QOu|?bj@``L~{tj1M(3ohB0fQgleN@DQnyEIn5 z3WlrUIZ^g?CB0<_YCt@*Za3~Z-O39;Dv!-7nu>cqI>LUvPr zr?%r=Fl?4AKZg%!mFXLr{`#nRQgA~Qo{6GM>qeu07f;kC8RGWi6l(8pg<%gaiS0M5 z=}q(*IuMn>9^c;RY|lktXg>aI_(*rlyh*ul7$$SRV(->U^3v=Jm5E{Sof1JiK3}4j zt92<=W8%7LtvNu00)yePwNo63l^}8FG3w*R*~f!dY1;7( zw5nPOHFJBRcPw)q-Jq;O|d81WzL9MiY_(}5ZuK=ss#U$4-9Xc;fQTk2= zZoAq2zVs`p6?svkdLG{L@9x6$jl#!nA{mu6(WA-!R5Du;>orZ-57dR^z1OmTf_dZr zjYiJ(Qu;4H2!3zeQLht)Yi@Fg@qa3Ecif{MmC~S~KoNGXh`xJrmc1lUvaU3rY}6D< zmvh%sd2etev4NI`OGtZQov11=z#fIJ6w)U}5?^Bm?MM@--!r1!@%Avt7=y3`L-?2t zLsfzv)_7!+L8&>Vbo0T6Ro_K=vl>}Od!hLGYHFFHM+w)uVoBLpcpM#v2kcHy*~aH zVjsJpOP_RFHMk3O_m_*CEzFU#W|rLn9mKtTCX6q(P>R}haeS>c?d8nFyPMlZ0<9ni z&cz&dn2Jlx&v-JxA5G@GzV=-%iJr*w^!w{5RbdbH^Up`C)@AV~qlmJ)^uU}+(l`*q zOw!OwdYy1Um@y-|dQ_Rj{De16I-cjUdXE%)lYl|)cj?cSp_sYE2rKlsS3Q&aC3_Ci zw5kz!S7n3;EfQvODS*zdp+VdAY0X7*JT=T=c7qcwE9pzy90GY3V1{j-eQE58Ed2bV zhX+>Pw06y4bUmOBY5GK+FOw1Vht)ypz~tYwsFiO9f=o0IAG7d`G>+CcH|XGzSNHI#m`7mUgU zC0YNb@x8Z_?%lcM`=1w9-ZMbn(Ni=u_Zw$xy-_s#EzK%&!l{D~sQ9EArgUAxGnfi` zy!aYT_Gbo`lLcbu|0bI*35bh4EjiXd7yd5E*lfOr?-JZgub7Hu3vbZ;%V~JE#h7*r z2}SYl;o-pzwDx-f64T6R=+|pv@whlreR+!VnTOri=NWy!qKov?mnd6aTc}QaM9=I7 zqBv?9jn!qBS8ET*bsC8K?2E2zX_BY~7*g!FIn=Z`1YJIKkZh|76sZ^L2ROpjZVPpN zKM*I!?4ji&Ct%avJ``4FNV~lvFw4>!=TfXlDsT}Qa<+Jla|rovcgKyo7o;Ekf@0>} zajB{JN7nnSu~SPME>CJHDK(0+-@c$1Gnlc!dAzfmB1Ox`|3v;c&K}Gd3ZI$%xwl#9 zlH7yyBN{*-wt-L*K&*+MdL&e-F5PV%Fr7k5PM(f7n!${uTh9|6povC>4e=~;>o z?FGepJA8iEB%*7TVIdt2_w7>H`{WJX-}HwR_dKN7j(7y96wvomFX%}?H(bgdgf(_c zM43t~J&|dohGRE z)s>E?&A@K{JeZO~PuG8=#r^xEwBbFy`07r2OYJaE(kV_Y1ks+j$1I7OueLoY#v;#S+^TE_-a;!r>rF6&}KTY~tS znuaI8>V(Yu-}G(PQ+hh5Rq}MnOwQLDQ%N2>tAZ3L?9LUED@sPi{T4B|F$d;1dXeqw zbg|_|7F~#4PD#V~Y=6cMeyzJ{9-qf8&90N<+aNT$CBblLI92SjL0-}zbPnkaDJMbt zOT6)Ov7w~0bO$B%2*Alf6R<(zjqatt#gaZXBsaS^B4Wo;P9byMj=G}no^v#!N(Xux z-J#rhpY9IxpwHQZ(Nvg-hQcm%E?O2g{*LerTp;fCSB1|_J*ZD9p|jTa>3Wxm*f3=V zZoG{{L%}r6o6Y&|dv~eiBX<~X@lJe51WrnSq0#l+0lue*2V*U9EzAVTBiB$>)J$eD zAEVLHPUs!7fVOT)MD+mnKsUdqY)==+|5T-?mOsfb={|Ka?4YSv$3t<@8R7EC2ERL= zQ`ts{aZ%IA@2M0lMj0TZ!WdaSN8s5ZJ-l^WEj$9%X`aV>VI;qdLNs{qxZMHfoRe|z?BR&snhCX{ zsdRGS5#hZc34Q}&k@MxUI62`oc^7&h&5ZY_6dV$9e?j#B-njHqT-vuA}0X8JJ;ujpiI2jUPAeQ{fn8cxKkoOXHQ~ zJ2MU)XSHCE96<{YjbauDXy%QfxV595*4^`iQ|f#d{z4@osemO;b5SONacT#0fDlOz@#~=0kAZUlw*V#^Wsa>DqM)m?KwA zcRadF9^C1Mj9G8#dDAjF&uouTJa21}ZzJ6k=Azn*pBWQr+;&cq4v_zF>$RAzcefb()@*PO}+I*doaK1`eS9txY65Rve zh=7hTYR^{#lC(%p%ZFw}OyYi9o#cF^CWUN#Evj@4sJNCL+F=g(vCbN^_ROdCr-tIJ z!~jG6&y(eR?#oHyaA?gXGWs2k!h4>$tQ*f~iuq#k8TLx@SyG4JvB~FEXt`@7g{8NU zD|<@1C1t_$_9p6a_oWC}bDu7~8iD-mB`49t%2lY;>t(s1X~c!Zv?fj@J6&QvO5a7;AHdMu%qt$XNAHqXmBH`MX3 zm>S17k;1e@JodavX9tYJykzF&4g5*luUbP!o?skYO0s~BRaO)1$?K{QW zHP!U{v^|wb5z-$_B6PBUXr@0>96e#8x|e#La-iZ?buqEClZ@y~cy$SPufQNWcl_i=c`?)Fv1Uk1GmtG^dh>Fu}AC< znn-UNb1{nZ>+%|&^u;;>1G+w@NSca+dN;)d?f=N**B~g(big{!k*<9efZ9IX2|s;E zM0xAMwK5cKC1bGQryO|{2jZieJ3JlC$#+s5$|KU@SGrrYa>x3&ttEEX=%KZfcaj&^ z(}Rbrgml7Da?N5_-;W4LH4Vh$aA|sM6^G&ce3#0*!F%pleAPBZh^)7y$};$3E<99L3XLMpZR?sM>``}|_Nu4MezN#+{uHGpI76fO7mZAs z06+I&ESl;`-{f2n&TPJZ{}d6o!Hu(9I*78hr{yz^G4U@m&)9o!j7{drIsJrH^wYJ6+37xvZL##nSJ3bkBa9nX{jHYL!XkdB z3UjI7jwmQ!`$e_uO)y;Q2(^73N;}SZQBbNTjwClo)D|dV>0KfIjY*?n&Ch7l_jbwL zkvk>-zY})c;(bEA9X{*;>k+e@R?tI+I$3Uu~S4;U}znM=xE@@lle0?l=#GNXu` zRGlF|EEShzLr~FnLo6=3AVSV2lf{7D)aas!gh%D1wfQkkET4qc$GYM7K1=Lb?}uk2 ztSR*GHZo{FM)xpLOp5zN{?>^&z2p&9GY8mq41c~a$D{hQCMCV@NkjiWAsvY!Bpa=e z%kPe^K66~QE4&dJEi@YXLQaC2*?q{9zh9nb z8pHF_S?pv3ANlC4&!v$i6D8Gc;bMgw=X^n9=Jd?JpQW2iHoWsZ@ndy|5JK$2QW#BOc=9LtQlNlZTA&9-+64-%bB( z?7ZWte*f@KNmfK=R#qewg>dfIMHCq!n=+CRLWq*Ii?p}Wu1`BkiuP90mi8i*N@;1R zey{KEpWnZ~KYH{>$8ma}_c`}{zpm?gUe4o0MVm8@?bOG;m>jfy%Edzy?(53@M`L@FQ|T+hXv1Ae(Xkt(@``7}HL)&jwvQ!*@?IP*SQ94X|+a(X&N4~6CZaB{3YXRn5{Cw7r!`JHwO-pm@b z24^cqMPPQfYTEjxC#<@zB*h`+bdB%Jy$uJ&G{<0CWcHoRKebYXNirl>JnPpTC6+|W zQA0sKw!|f)J+?_0dw-z7kzQC}Q%Y|t-JtX10A0H)3-!-DFPSr&3f(0*p1+SS@SauI z&<}&lI>e&@b0o2L*|t*+YOb2loMi {zYbzB`UAD-pFkuZ-fHM{rL$+&QBI)zlnB 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 PjOvP)XyQ$A76-u}qHA2# diff --git a/onnxruntime/test/testdata/transform/computation_reduction/gathernd_layernormalization.onnx b/onnxruntime/test/testdata/transform/computation_reduction/gathernd_layernormalization.onnx deleted file mode 100644 index 4098cdd8a006d1a9c92a9b98ea2dfd5cc5a65644..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1693 zcmb7^X;4#F6vvGQ5+A7WkTy_?3tK@G1$W3he+36D0@kJChVhX+AdLy0GpR zQOs2fxxCqG5+WbEGnZtHi&3;@+nL^}g3YcGM7_lz*fb_S&pAhEEZKJFp(dftOtRR_ znjFEHo?&Og-pxDJ$V;r->ts6786M8MN&F1Kpfd}+7|yb945K(hC)o|U8N4mr*Zp5_ zU3gFSA2M$;=JR%=MGWi8$oX8OqtB)i(|ESM>5uUuIm^N>ZqR~h3AGHOycQRRX_ ztXaRA&idWs1|_JWsGP@*5(i>>nFrL?+tl^68LCh-o;Q2~+lj%LG=3r-a}l|LHQTs3 zw)r%)<9J+}=8cgrqscF68g44np!w<=jd)l>fssSNF1$;cDL;^`bpyrLxx&ZV1tBMc z&^o~r&!t0jE~$Wy-Rud|rh}xowwwESVF9=2r#&>J(Si{dEm*d%nd)}k<+Q_!XwfV? zGHYX_j6-Ha6_Y#0G6c)x0LhWsll2^_`Ono%zzPS^XwDke?s~$(Ivadwl zyEz+$J>+Pwyhx=x=QAS9zZ z`YX)zILixL>H}d(-$C{3r_tO`_tO>sLJB(XftcdHm^(0?6y`uQU3O4qYc&aZz~<$x zv}bM#9OZI^clM#xwcbc{NK|#lhn{9l$BtfOv1*YIdEH{5-`E|}5eq!ib10@U8AD$w z5m8!AXR8{yrU4fy=6n*Bj$TG{wV_xnMWg;vEv-ww!JYMZ&P}Y6V|&DBlu}osE$|J+ z^+*OKF~u~Me?%cAlWB>o39GM~Ab(KBoeu7X1UCbE#5Gf_cM)yf+Y_6HvWO4rgj|II zC2X5qb2G_d)sP z0obbT1tB;DKBgwFtULqz8-j6d_GVJoso>JMh-;WqOD|%*@XXi|wpul|#mD37lsVdG zzb3*ktOJr)c1K-_K`VynkbfwWCWXA!ZPuUhQ_5HsqhMWL>l347T_qvQB#2B0rzA}p z{lB``hfymPZ0Nrkd|8ztPvp%;z0PVA3`TvMKI-(AY|+lNSISZ&nYU8O_GL6qc-Xsz dwp}M$&b0GzkM?9b=`CiBlVGz*mNdJE>@OD&iU$Ay diff --git a/onnxruntime/test/testdata/transform/computation_reduction/gathernd_matmul.onnx b/onnxruntime/test/testdata/transform/computation_reduction/gathernd_matmul.onnx deleted file mode 100644 index 0295c60154423072e4ec8257e2f415e6aa071b9f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 65963 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 GeneratePreTrainingTransformers( ORT_THROW_IF_ERROR(rule_transformer->Register(std::make_unique())); // Remove duplicate nodes. Must be applied before any recompute transformations. - transformers.emplace_back(std::make_unique(compatible_eps)); + if (config.gelu_recompute || config.attn_dropout_recompute || config.transformer_layer_recompute) { + transformers.emplace_back(std::make_unique(compatible_eps)); + } else { + transformers.emplace_back(std::make_unique(compatible_eps)); + } transformers.emplace_back(std::make_unique(compatible_eps)); transformers.emplace_back(std::make_unique(compatible_eps)); @@ -120,9 +124,10 @@ std::vector> GeneratePreTrainingTransformers( execution_provider, false /*skip_dequantize_linear*/, compatible_eps, excluded_initializers)); transformers.emplace_back(std::make_unique(compatible_eps)); transformers.emplace_back(std::make_unique(compatible_eps)); -#if defined(USE_CUDA) || defined(USE_ROCM) - transformers.emplace_back(std::make_unique(compatible_eps)); -#endif + + if (config.enable_compute_optimizer) { + transformers.emplace_back(std::make_unique(compatible_eps)); + } if (config.gelu_recompute) { transformers.emplace_back(std::make_unique()); } @@ -195,11 +200,11 @@ InlinedVector> GenerateTransformers( case TransformerLevel::Level1: { InlinedHashSet l1_execution_providers = {}; InlinedHashSet cuda_rocm_execution_providers = {onnxruntime::kCudaExecutionProvider, - onnxruntime::kRocmExecutionProvider}; + onnxruntime::kRocmExecutionProvider}; // TODO hack - constant folding currently doesn't work after mixed precision transformation so it's disabled for now // ORT uses CPU kernels to evaluate constant values but some of them don't support fp16 - //transformers.emplace_back(std::make_unique(l1_execution_providers)); + // transformers.emplace_back(std::make_unique(l1_execution_providers)); transformers.emplace_back(std::make_unique(l1_execution_providers)); transformers.emplace_back(std::make_unique(free_dimension_overrides)); transformers.emplace_back(std::make_unique(cuda_rocm_execution_providers)); diff --git a/orttraining/orttraining/models/runner/training_runner.cc b/orttraining/orttraining/models/runner/training_runner.cc index ef875a5f1c..4eada66cd1 100644 --- a/orttraining/orttraining/models/runner/training_runner.cc +++ b/orttraining/orttraining/models/runner/training_runner.cc @@ -192,6 +192,7 @@ Status TrainingRunner::Initialize() { gt_config.gelu_recompute = params_.gelu_recompute; gt_config.transformer_layer_recompute = params_.transformer_layer_recompute; gt_config.number_recompute_layers = params_.number_recompute_layers; + gt_config.enable_compute_optimizer = true; config.graph_transformer_config = gt_config; } @@ -580,7 +581,7 @@ void TrainingRunner::RunWithUpdate(VectorString& feed_names, ORT_THROW_IF_ERROR(status); } catch (std::exception&) { - // If exception happens during worker execution, propogate the exception to main thread. + // If exception happens during worker execution, propagate the exception to main thread. pipeline_worker_pool_.worker_states[worker_id].execution_exception = std::current_exception(); } }, diff --git a/orttraining/orttraining/python/orttraining_pybind_state.cc b/orttraining/orttraining/python/orttraining_pybind_state.cc index fe245bdd5d..1dbeb6e6ad 100644 --- a/orttraining/orttraining/python/orttraining_pybind_state.cc +++ b/orttraining/orttraining/python/orttraining_pybind_state.cc @@ -711,6 +711,7 @@ void addObjectMethodsForTraining(py::module& m, ExecutionProviderRegistrationFn .def_readwrite("gelu_recompute", &TrainingGraphTransformerConfiguration::gelu_recompute) .def_readwrite("transformer_layer_recompute", &TrainingGraphTransformerConfiguration::transformer_layer_recompute) .def_readwrite("number_recompute_layers", &TrainingGraphTransformerConfiguration::number_recompute_layers) + .def_readwrite("enable_compute_optimizer", &TrainingGraphTransformerConfiguration::enable_compute_optimizer) .def_readwrite("propagate_cast_ops_config", &TrainingGraphTransformerConfiguration::GraphTransformerConfiguration::propagate_cast_ops_config); py::class_ module_graph_builder_config( diff --git a/orttraining/orttraining/python/training/ortmodule/_graph_execution_manager.py b/orttraining/orttraining/python/training/ortmodule/_graph_execution_manager.py index 82c00bc47d..453bf64efe 100644 --- a/orttraining/orttraining/python/training/ortmodule/_graph_execution_manager.py +++ b/orttraining/orttraining/python/training/ortmodule/_graph_execution_manager.py @@ -177,6 +177,12 @@ class GraphExecutionManager(GraphExecutionInterface): # Memory aware gradient builder. self._use_memory_efficient_gradient = False + # Enable compute optimizer by default. Allowed to be disabled via environment variable for + # convergence parity investigation. + self._enable_compute_optimizer = ( + ortmodule._defined_from_envvar("ORTMODULE_ENABLE_COMPUTE_OPTIMIZER", 1, warn=True) == 1 + ) + # Flag to re-export the model due to attribute change on original module. # Re-export will be avoided if _skip_check is enabled. self._original_model_has_changed = False @@ -445,6 +451,7 @@ class GraphExecutionManager(GraphExecutionInterface): graph_transformer_config.propagate_cast_ops_config.level = self._propagate_cast_ops_level graph_transformer_config.propagate_cast_ops_config.allow = self._propagate_cast_ops_allow graph_transformer_config.propagate_cast_ops_config.strategy = self._propagate_cast_ops_strategy + graph_transformer_config.enable_compute_optimizer = self._enable_compute_optimizer return graph_transformer_config def _initialize_graph_builder(self): diff --git a/orttraining/orttraining/test/training_api/core/checkpoint_test.cc b/orttraining/orttraining/test/training_api/core/checkpoint_test.cc index 51c6392ff5..a9af9a8e8b 100644 --- a/orttraining/orttraining/test/training_api/core/checkpoint_test.cc +++ b/orttraining/orttraining/test/training_api/core/checkpoint_test.cc @@ -48,12 +48,12 @@ namespace { * Then load it into ORT, compare with the initial parameter values. */ TEST(CheckpointApiTest, SaveOnnxModelAsCheckpoint_ThenLoad_CPU) { - /// Phase 1 - Test Preparison + /// Phase 1 - Test Preparation /// Prepare the data and dest folder for saving checkpoint. /// Also cooked the data for test result comparison. // Model path and trainable parameter name definitions. - auto model_uri = MODEL_FOLDER "transform/computation_reduction/e2e.onnx"; + auto model_uri = MODEL_FOLDER "transform/computation_reduction/gathernd/e2e.onnx"; std::vector expected_trainable_param_names{ "bert.encoder.layer.2.output.LayerNorm.weight", "bert.encoder.layer.2.output.LayerNorm.bias", @@ -88,7 +88,7 @@ TEST(CheckpointApiTest, SaveOnnxModelAsCheckpoint_ThenLoad_CPU) { ORT_ENFORCE(CreateOrtValuesFromTensorProtos(trainable_param_values, expected_trainable_param_name_to_ort_value) .IsOK()); - // Remove the tempoprary directory if it already exists. + // Remove the temporary directory if it already exists. auto ckpt_test_root_dir = ORT_TSTR("checkpointing_api_test_dir"); if (Env::Default().FolderExists(ckpt_test_root_dir)) { ORT_ENFORCE(Env::Default().DeleteFolder(ckpt_test_root_dir).IsOK()); @@ -120,7 +120,7 @@ TEST(CheckpointApiTest, SaveOnnxModelAsCheckpoint_ThenLoad_CPU) { ASSERT_EQ(expected_file_names, valid_file_names); /// Phase 3 - Run load checkpoint APIs. - /// And check the result comparible with initial parameter values. + /// And check the result comparable with initial parameter values. // Call Load APIs CheckpointState checkpoint_state_to_load; @@ -199,7 +199,7 @@ TEST(CheckpointApiTest, LoadCheckpointToModel) { #if defined(USE_CUDA) || defined(USE_ROCM) TEST(CheckpointApiTest, SaveOptimizerStateAsCheckpoint_ThenLoad_CUDA) { - /// Phase 1 - Test Preparison + /// Phase 1 - Test Preparation /// Prepare the data and dest folder for saving checkpoint. /// Also cooked the data for test result comparison. auto model_uri = MODEL_FOLDER "training_api/training_model.onnx"; @@ -252,7 +252,7 @@ TEST(CheckpointApiTest, SaveOptimizerStateAsCheckpoint_ThenLoad_CUDA) { CheckpointState checkpoint_state; ORT_ENFORCE(optimizer->GetStateDict(checkpoint_state.optimizer_checkpoint_state).IsOK()); - // Remove the tempoprary directory if it already exists. + // Remove the temporary directory if it already exists. auto ckpt_test_root_dir = ORT_TSTR("checkpointing_api_test_dir"); if (Env::Default().FolderExists(ckpt_test_root_dir)) { ORT_ENFORCE(Env::Default().DeleteFolder(ckpt_test_root_dir).IsOK()); @@ -287,7 +287,7 @@ TEST(CheckpointApiTest, SaveOptimizerStateAsCheckpoint_ThenLoad_CUDA) { ASSERT_EQ(expected_file_names, valid_file_names); /// Phase 3 - Run load checkpoint APIs. - /// And check the result comparible with initial optimizer state values. + /// And check the result comparable with initial optimizer state values. // Call Load APIs CheckpointState checkpoint_state_to_load; @@ -334,7 +334,7 @@ TEST(CheckpointApiTest, SaveOptimizerStateAsCheckpoint_ThenLoad_CUDA) { * Then load it into ORT, compare with the initial properties' values. */ TEST(CheckpointApiTest, SaveCustomPropertyAsCheckpoint_ThenLoad_CPU) { - /// Phase 1 - Test Preparison + /// Phase 1 - Test Preparation /// Prepare the data and dest folder for saving checkpoint. CheckpointState checkpoint_state; @@ -352,7 +352,7 @@ TEST(CheckpointApiTest, SaveCustomPropertyAsCheckpoint_ThenLoad_CPU) { std::string s_property_name("train_data_path"); property_bag.AddProperty(s_property_name, s_data); - // Remove the tempoprary directory if it already exists. + // Remove the temporary directory if it already exists. auto ckpt_test_root_dir = ORT_TSTR("checkpointing_api_test_dir"); if (Env::Default().FolderExists(ckpt_test_root_dir)) { ORT_ENFORCE(Env::Default().DeleteFolder(ckpt_test_root_dir).IsOK()); diff --git a/orttraining/orttraining/training_ops/cuda/communication/nccl_service.h b/orttraining/orttraining/training_ops/cuda/communication/nccl_service.h index f9f2d0a5f9..601d8ccb31 100644 --- a/orttraining/orttraining/training_ops/cuda/communication/nccl_service.h +++ b/orttraining/orttraining/training_ops/cuda/communication/nccl_service.h @@ -187,7 +187,7 @@ class NcclService final : public INcclService { // Search the next unfinished communication group to work on. int FindNextCommunicationTime() const; - // Mutex to gurantee thread-safe access to this class. + // Mutex to guarantee thread-safe access to this class. std::mutex mutex_; // Conditional variable used to wait for the mutex. std::condition_variable cv_;