[GPU] improve primitive impl caching mechanism with new unified key (#14797)

* [GPU] improved impl cache key (#14797)
- Add hash function for primitive and program_node
- Filter task before entering async compilation queue

* [GPU] improved impl cache key (#14797)
- Multiply magic prime number at input value of hash_combine to avoid hash collision

* [GPU] Update codes to follow up review comments (#14797)
- Change func name from pop_front_task to erase_front_task
- Change func name from get_layout_key to get_impl_key
- Remove average_unpooling.hpp because it was alread removed
- Replace std::list to std::deque in compilation_context
- Modify layout::hash() to get hash of shape from partial shape
- Remove calculation code to get hash from static layout in program_node => layout hash is calculated outside of program_node

* [GPU] Update gpu functional test for improved impl key (#14797)

* [GPU] update compilation queue (#14797)

* [GPU] Move type_string hash to primitive (#14797)
- Add hash for num_outputs in program_node

* [GPU] update hash functions for program_node (#14797)
- add hash for number of inputs in program_node
- program node::hash() had separated into void program node::caclulate_hash() and size_t program_node::get_hash()

* [GPU] Fix gpu unit test failures (#14797)
- move the location to calculate all nodes from compile_graph to program ctor

* [GPU] Fix build issue after rebase (#14797)

* [GPU] Update impl if optimized kernel is in impl_cache even if the shape does not change. (#14797)
- Apply improved hash key to mem kernels cache in update_weight
- Add missing hash value for broadcast
- Add simple unit test to check hash value for program_node, primitive and program_inst
This commit is contained in:
Paul Youngsoo Ahn authored and GitHub committed 2023-01-30 14:35:58 -08:00
1 parent c2518f1e4a
commit 0b5603fa98
97 files changed
+1517 -64

No files matched your search

@@ -250,6 +250,7 @@ public:
void remove_kernel(kernel_id id);
bool is_local_block_io_supported() const;
void query_local_block_io_supported();
void calc_nodes_hash();
private:
uint32_t prog_id = 0;
@@ -116,6 +116,15 @@ struct activation : public primitive_base<activation> {
/// All other dimensions should be 1.
primitive_id additional_params_input;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, activation_function);
seed = hash_combine(seed, additional_params.a);
seed = hash_combine(seed, additional_params.b);
seed = hash_combine(seed, additional_params_input.empty());
return seed;
}
protected:
std::vector<std::reference_wrapper<const primitive_id>> get_dependencies() const override {
if (additional_params_input.empty())
@@ -50,6 +50,14 @@ struct adaptive_pooling : public primitive_base<adaptive_pooling> {
primitive_id indices_output;
data_types index_element_type{data_types::i64};
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, mode);
seed = hash_combine(seed, index_element_type);
seed = hash_combine(seed, indices_output.empty());
return seed;
}
protected:
std::vector<std::reference_wrapper<const primitive_id>> get_dependencies() const override {
std::vector<std::reference_wrapper<const primitive_id>> ret;
@@ -53,5 +53,15 @@ struct arg_max_min : public primitive_base<arg_max_min> {
ov::op::TopKSortType sort;
/// @brief Sets output order: if True than first output contains values and second (optional) - indices.
bool values_first;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, mode);
seed = hash_combine(seed, top_k);
seed = hash_combine(seed, axis);
seed = hash_combine(seed, sort);
seed = hash_combine(seed, values_first);
return seed;
}
};
} // namespace cldnn
@@ -63,5 +63,13 @@ struct batch_to_space : public primitive_base<batch_to_space> {
tensor crops_begin;
tensor crops_end;
tensor out_size;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, block_shape.hash());
seed = hash_combine(seed, crops_begin.hash());
seed = hash_combine(seed, crops_end.hash());
return seed;
}
};
} // namespace cldnn
@@ -65,6 +65,17 @@ struct binary_convolution : public primitive_base<binary_convolution> {
/// @brief List of primitive ids containing weights data.
const primitive_id_arr weights;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_range(seed, pad.begin(), pad.end());
seed = hash_range(seed, stride.begin(), stride.end());
seed = hash_range(seed, dilation.begin(), dilation.end());
seed = hash_combine(seed, groups);
seed = hash_combine(seed, pad_value);
seed = hash_combine(seed, weights.size());
return seed;
}
std::vector<std::reference_wrapper<const primitive_id>> get_dependencies() const override {
std::vector<std::reference_wrapper<const primitive_id>> ret;
ret.reserve(weights.size());
@@ -71,5 +71,14 @@ struct border : public primitive_base<border> {
ov::op::PadMode pad_mode;
/// @brief Border value that is used in constant mode.
float pad_value;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_range(seed, pads_begin.begin(), pads_begin.end());
seed = hash_range(seed, pads_end.begin(), pads_end.end());
seed = hash_combine(seed, pad_mode);
seed = hash_combine(seed, pad_value);
return seed;
}
};
} // namespace cldnn
@@ -128,5 +128,12 @@ struct broadcast : public primitive_base<broadcast> {
/// @brief Array of axes positions from output shape (0-based, from left to right)
/// along which broadcast should happen.
std::vector<uint16_t> broadcast_axes;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_range(seed, broadcast_axes.begin(), broadcast_axes.end());
seed = hash_range(seed, axes_mapping.begin(), axes_mapping.end());
return seed;
}
};
} // namespace cldnn
@@ -25,6 +25,12 @@ struct bucketize : primitive_base<bucketize> {
with_right_bound(with_right_bound) {}
bool with_right_bound;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, with_right_bound);
return seed;
}
};
} // namespace cldnn
@@ -58,5 +58,11 @@ struct concatenation : public primitive_base<concatenation> {
/// @brief Dimension along which concatenation should take place
int64_t axis;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, axis);
return seed;
}
};
} // namespace cldnn
@@ -50,5 +50,13 @@ struct convert_color : public primitive_base<convert_color> {
color_format output_color_format;
memory_type mem_type;
layout output_layout;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, input_color_format);
seed = hash_combine(seed, output_color_format);
seed = hash_combine(seed, mem_type);
return seed;
}
};
} // namespace cldnn
@@ -763,6 +763,24 @@ struct convolution : public primitive_base<convolution> {
/// @brief List of primitive ids containing compensation.
primitive_id_arr compensation;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_range(seed, pad.begin(), pad.end());
seed = hash_range(seed, stride.begin(), stride.end());
seed = hash_range(seed, dilation.begin(), dilation.end());
seed = hash_combine(seed, groups);
seed = hash_combine(seed, deformable_groups);
seed = hash_combine(seed, deformable_mode);
seed = hash_combine(seed, bilinear_interpolation_pad);
seed = hash_combine(seed, grouped_weights_shape);
seed = hash_combine(seed, weights.size());
seed = hash_combine(seed, bias.size());
seed = hash_combine(seed, weights_zero_points.size());
seed = hash_combine(seed, activations_zero_points.size());
seed = hash_combine(seed, compensation.size());
return seed;
}
std::vector<std::reference_wrapper<const primitive_id>> get_dependencies() const override {
std::vector<std::reference_wrapper<const primitive_id>> ret;
ret.reserve(weights.size() + bias.size() + weights_zero_points.size() +
@@ -826,6 +844,20 @@ struct deformable_interp : public primitive_base<deformable_interp> {
/// @brief if bilinear_interpolation_pad is true and the sampling location is within one pixel outside
/// of the feature map boundary, then bilinear interpolation is performed on the zero padded feature map.
bool bilinear_interpolation_pad {false};
size_t hash() const override {
size_t seed = primitive::hash();
seed = cldnn::hash_range(seed, pad.begin(), pad.end());
seed = cldnn::hash_range(seed, stride.begin(), stride.end());
seed = cldnn::hash_range(seed, dilation.begin(), dilation.end());
seed = cldnn::hash_combine(seed, kernel_size.hash());
seed = cldnn::hash_combine(seed, groups);
seed = cldnn::hash_combine(seed, deformable_groups);
seed = cldnn::hash_range(seed, padding_above.begin(), padding_above.end());
seed = cldnn::hash_range(seed, padding_below.begin(), padding_below.end());
seed = cldnn::hash_combine(seed, bilinear_interpolation_pad);
return seed;
}
};
struct deformable_conv : public primitive_base<deformable_conv> {
@@ -853,6 +885,14 @@ struct deformable_conv : public primitive_base<deformable_conv> {
/// @brief List of primitive ids containing bias data.
const primitive_id_arr bias;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, groups);
seed = hash_combine(seed, weights.size());
seed = hash_combine(seed, bias.size());
return seed;
}
std::vector<std::reference_wrapper<const primitive_id>> get_dependencies() const override {
std::vector<std::reference_wrapper<const primitive_id>> ret;
ret.reserve(weights.size() + bias.size());
@@ -124,5 +124,15 @@ struct crop : public primitive_base<crop> {
size_t num_splits = 1;
/// @brief original ngraph operation type
crop_ngraph_op_mode op_mode;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, reference_input.hash());
seed = hash_combine(seed, offsets.hash());
seed = hash_combine(seed, output_idx);
seed = hash_combine(seed, num_splits);
seed = hash_combine(seed, op_mode);
return seed;
}
};
} // namespace cldnn
@@ -31,5 +31,13 @@ struct ctc_greedy_decoder : public primitive_base<ctc_greedy_decoder> {
bool ctc_merge_repeated;
tensor output_tensor;
primitive_id second_output;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, blank_index);
seed = hash_combine(seed, ctc_merge_repeated);
seed = hash_combine(seed, second_output.empty());
return seed;
}
};
} // namespace cldnn
@@ -33,6 +33,14 @@ struct ctc_loss : primitive_base<ctc_loss> {
bool preprocess_collapse_repeated;
bool ctc_merge_repeated;
bool unique;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, preprocess_collapse_repeated);
seed = hash_combine(seed, ctc_merge_repeated);
seed = hash_combine(seed, unique);
return seed;
}
};
} // namespace cldnn
@@ -32,5 +32,13 @@ struct cum_sum : public primitive_base<cum_sum> {
bool exclusive;
/// @brief If set to true will perform the sums in reverse direction.
bool reverse;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, axis);
seed = hash_combine(seed, exclusive);
seed = hash_combine(seed, reverse);
return seed;
}
};
} // namespace cldnn
@@ -73,5 +73,12 @@ struct custom_gpu_primitive : public primitive_base<custom_gpu_primitive> {
const std::vector<size_t> lws;
/// @brief Source code for the kernel
const primitive_id_arr kernels_code;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, kernel_entry_point);
seed = hash_combine(seed, kernels_code.size());
return seed;
}
};
} // namespace cldnn
@@ -25,5 +25,11 @@ struct data : public primitive_base<data> {
/// @brief @ref memory object which contains data.
/// @note If memory is attached by memory::attach(), the attached buffer should be valid till network build.
memory::ptr mem;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, id);
return seed;
}
};
} // namespace cldnn
@@ -375,6 +375,17 @@ struct deconvolution : public primitive_base<deconvolution> {
/// @brief List of primitive ids containing bias data.
const primitive_id_arr bias;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_range(seed, pad.begin(), pad.end());
seed = hash_range(seed, stride.begin(), stride.end());
seed = hash_combine(seed, groups);
seed = hash_combine(seed, grouped_weights_shape);
seed = hash_combine(seed, weights.size());
seed = hash_combine(seed, bias.size());
seed = hash_combine(seed, output_shape_id.empty());
return seed;
}
protected:
std::vector<std::reference_wrapper<const primitive_id>> get_dependencies() const override {
@@ -38,5 +38,12 @@ struct depth_to_space : public primitive_base<depth_to_space> {
size_t block_size;
/// @brief depth division mode
depth_to_space_mode mode;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, block_size);
seed = hash_combine(seed, mode);
return seed;
}
};
} // namespace cldnn
@@ -120,6 +120,29 @@ struct detection_output : public primitive_base<detection_output> {
/// @brief Clip decoded boxes after nms step
const bool clip_after_nms;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, num_classes);
seed = hash_combine(seed, keep_top_k);
seed = hash_combine(seed, share_location);
seed = hash_combine(seed, background_label_id);
seed = hash_combine(seed, nms_threshold);
seed = hash_combine(seed, top_k);
seed = hash_combine(seed, eta);
seed = hash_combine(seed, code_type);
seed = hash_combine(seed, variance_encoded_in_target);
seed = hash_combine(seed, confidence_threshold);
seed = hash_combine(seed, prior_info_size);
seed = hash_combine(seed, prior_coordinates_offset);
seed = hash_combine(seed, prior_is_normalized);
seed = hash_combine(seed, input_width);
seed = hash_combine(seed, input_height);
seed = hash_combine(seed, decrease_label_id);
seed = hash_combine(seed, clip_before_nms);
seed = hash_combine(seed, clip_after_nms);
return seed;
}
protected:
};
@@ -55,6 +55,15 @@ struct dft : public primitive_base<dft> {
ov::Shape output_shape;
dft_direction direction;
dft_mode mode;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_range(seed, axes.begin(), axes.end());
seed = hash_range(seed, signal_size.begin(), signal_size.end());
seed = hash_combine(seed, direction);
seed = hash_combine(seed, mode);
return seed;
}
};
} // namespace cldnn
@@ -167,5 +167,15 @@ struct eltwise : public primitive_base<eltwise> {
std::vector<tensor> stride;
/// @brief Define auto broadcast rule specification.
ov::op::AutoBroadcastSpec broadcast_spec;
size_t hash() const override {
size_t seed = primitive::hash();
seed = cldnn::hash_combine(seed, mode);
seed = cldnn::hash_range(seed, coefficients.begin(), coefficients.end());
for (auto& s : stride) {
seed = cldnn::hash_combine(seed, s.hash());
}
return seed;
}
};
} // namespace cldnn
@@ -38,5 +38,12 @@ struct embedding_bag : public primitive_base<embedding_bag> {
tensor output_shape;
/// @brief Default index
int32_t default_index;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, type);
seed = hash_combine(seed, default_index);
return seed;
}
};
} // namespace cldnn
@@ -71,6 +71,21 @@ struct experimental_detectron_detection_output : public primitive_base<experimen
float max_delta_log_wh;
std::vector<float> deltas_weights;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, score_threshold);
seed = hash_combine(seed, nms_threshold);
seed = hash_combine(seed, num_classes);
seed = hash_combine(seed, post_nms_count);
seed = hash_combine(seed, max_detections_per_image);
seed = hash_combine(seed, class_agnostic_box_regression);
seed = hash_combine(seed, max_delta_log_wh);
seed = hash_range(seed, deltas_weights.begin(), deltas_weights.end());
seed = hash_combine(seed, output_classes.empty());
seed = hash_combine(seed, output_scores.empty());
return seed;
}
protected:
std::vector<std::reference_wrapper<const primitive_id>> get_dependencies() const override {
std::vector<std::reference_wrapper<const primitive_id>> ret;
@@ -48,6 +48,16 @@ struct experimental_detectron_generate_proposals_single_image
int64_t pre_nms_count;
int64_t post_nms_count;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, min_size);
seed = hash_combine(seed, nms_threshold);
seed = hash_combine(seed, pre_nms_count);
seed = hash_combine(seed, post_nms_count);
seed = hash_combine(seed, output_roi_scores.empty());
return seed;
}
protected:
std::vector<std::reference_wrapper<const primitive_id>> get_dependencies() const override {
std::vector<std::reference_wrapper<const primitive_id>> ret;
@@ -46,6 +46,20 @@ struct experimental_detectron_prior_grid_generator
uint64_t featmap_width;
uint64_t image_height;
uint64_t image_width;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, flatten);
seed = hash_combine(seed, h);
seed = hash_combine(seed, w);
seed = hash_combine(seed, stride_x);
seed = hash_combine(seed, stride_y);
seed = hash_combine(seed, featmap_height);
seed = hash_combine(seed, featmap_width);
seed = hash_combine(seed, image_height);
seed = hash_combine(seed, image_width);
return seed;
}
};
} // namespace cldnn
@@ -40,6 +40,17 @@ struct experimental_detectron_roi_feature_extractor : public primitive_base<expe
std::vector<int64_t> pyramid_scales;
int sampling_ratio = 0;
bool aligned = false;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, output_dim);
seed = hash_combine(seed, pooled_height);
seed = hash_combine(seed, pooled_width);
seed = hash_range(seed, pyramid_scales.begin(), pyramid_scales.end());
seed = hash_combine(seed, sampling_ratio);
seed = hash_combine(seed, aligned);
return seed;
}
};
} // namespace cldnn
@@ -31,6 +31,12 @@ struct experimental_detectron_topk_rois : public primitive_base<experimental_det
/// maximal numbers of output ROIs.
size_t max_rois;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, max_rois);
return seed;
}
};
} // namespace cldnn
@@ -54,5 +54,14 @@ struct extract_image_patches : public primitive_base<extract_image_patches> {
std::string auto_pad;
/// @brief Shape of output layout
tensor output_shape;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_range(seed, sizes.begin(), sizes.end());
seed = hash_range(seed, strides.begin(), strides.end());
seed = hash_range(seed, rates.begin(), rates.end());
seed = hash_combine(seed, auto_pad);
return seed;
}
};
} // namespace cldnn
@@ -30,5 +30,11 @@ struct eye : public primitive_base<eye> {
tensor output_shape;
int32_t shift;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, shift);
return seed;
}
};
} // namespace cldnn
@@ -75,6 +75,13 @@ struct fully_connected : public primitive_base<fully_connected> {
/// @brief Primitive dimension size.
size_t input_size;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, input_size);
seed = hash_combine(seed, bias.empty());
return seed;
}
protected:
std::vector<std::reference_wrapper<const primitive_id>> get_dependencies() const override {
std::vector<std::reference_wrapper<const primitive_id>> ret;
@@ -44,5 +44,13 @@ struct gather : public primitive_base<gather> {
int64_t batch_dim;
/// @brief Support negative indexes
bool support_neg_ind;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, axis);
seed = hash_combine(seed, batch_dim);
seed = hash_combine(seed, support_neg_ind);
return seed;
}
};
} // namespace cldnn
@@ -42,5 +42,12 @@ struct gather_elements : public primitive_base<gather_elements> {
/// @brief Which axis to gather on.
int64_t axis;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, output_format.value);
seed = hash_combine(seed, axis);
return seed;
}
};
} // namespace cldnn
@@ -49,5 +49,13 @@ struct gather_nd : public primitive_base<gather_nd> {
/// @brief GatherND batch_merged_output
bool batch_merged_output;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, indices_rank);
seed = hash_combine(seed, batch_dims);
seed = hash_combine(seed, batch_merged_output);
return seed;
}
};
} // namespace cldnn
@@ -67,6 +67,15 @@ struct gemm : public primitive_base<gemm> {
size_t input_rank;
/// @brief Second matrix rank
size_t weight_rank;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, transpose_input0);
seed = hash_combine(seed, transpose_input1);
seed = hash_combine(seed, alpha);
seed = hash_combine(seed, beta);
return seed;
}
};
} // namespace cldnn
@@ -59,6 +59,20 @@ struct generate_proposals
float nms_eta;
data_types roi_num_type;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, min_size);
seed = hash_combine(seed, nms_threshold);
seed = hash_combine(seed, pre_nms_count);
seed = hash_combine(seed, post_nms_count);
seed = hash_combine(seed, normalized);
seed = hash_combine(seed, nms_eta);
seed = hash_combine(seed, roi_num_type);
seed = hash_combine(seed, output_rois_scores.empty());
seed = hash_combine(seed, output_rois_num.empty());
return seed;
}
protected:
std::vector<std::reference_wrapper<const primitive_id>> get_dependencies() const override {
std::vector<std::reference_wrapper<const primitive_id>> ret;
@@ -30,6 +30,14 @@ struct grid_sample : primitive_base<grid_sample> {
attributes(attributes) {}
GridSampleOp::Attributes attributes;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, attributes.align_corners);
seed = hash_combine(seed, attributes.mode);
seed = hash_combine(seed, attributes.padding_mode);
return seed;
}
};
} // namespace cldnn
@@ -26,5 +26,11 @@ struct grn : public primitive_base<grn> {
/// @brief Bias value for whole output tensor.
float bias;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, bias);
return seed;
}
};
} // namespace cldnn
@@ -30,5 +30,11 @@ struct input_layout : public primitive_base<input_layout> {
void change_layout(const cldnn::layout& new_layout) {
layout = new_layout;
}
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, id);
return seed;
}
};
} // namespace cldnn
@@ -167,6 +167,12 @@ struct loop : public primitive_base<loop> {
int64_t max_iteration;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, id);
return seed;
}
protected:
std::vector<std::reference_wrapper<const primitive_id>> get_dependencies() const override {
std::vector<std::reference_wrapper<const primitive_id>> ret{
@@ -60,5 +60,15 @@ struct lrn : public primitive_base<lrn> {
float beta;
/// @brief Normalize across or within channel
lrn_norm_region norm_region;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, size);
seed = hash_combine(seed, k);
seed = hash_combine(seed, alpha);
seed = hash_combine(seed, beta);
seed = hash_combine(seed, norm_region);
return seed;
}
};
} // namespace cldnn
@@ -124,6 +124,25 @@ struct lstm : public primitive_base<lstm> {
// tensor sequence_lens;
// /// @brief The sequence output for the hidden.
// uint32_t output_sequence;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, peepholes.empty());
seed = hash_combine(seed, clip);
seed = hash_combine(seed, input_forget);
seed = hash_range(seed, activations.begin(), activations.end());
for (auto& act_param : activation_params) {
seed = hash_combine(seed, act_param.a);
seed = hash_combine(seed, act_param.b);
}
seed = hash_combine(seed, output_selection);
seed = hash_combine(seed, offset_order);
seed = hash_combine(seed, bias.empty());
seed = hash_combine(seed, initial_hidden.empty());
seed = hash_combine(seed, initial_cell.empty());
return seed;
}
protected:
std::vector<std::reference_wrapper<const primitive_id>> get_dependencies() const override {
std::vector<std::reference_wrapper<const primitive_id>> ret;
@@ -178,6 +197,14 @@ struct lstm_gemm : public primitive_base<lstm_gemm> {
/// @brief direction default = 0, bidirectional = 1.
uint32_t direction;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, direction);
seed = hash_combine(seed, bias.empty());
seed = hash_combine(seed, hidden.empty());
return seed;
}
protected:
std::vector<std::reference_wrapper<const primitive_id>> get_dependencies() const override {
std::vector<std::reference_wrapper<const primitive_id>> ret;
@@ -240,6 +267,21 @@ struct lstm_elt : public primitive_base<lstm_elt> {
/// @brief direction default = 0, bidirectional = 1.
uint32_t direction;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, clip);
seed = hash_combine(seed, input_forget);
seed = hash_range(seed, activations.begin(), activations.end());
for (auto& act_param : activation_params) {
seed = hash_combine(seed, act_param.a);
seed = hash_combine(seed, act_param.b);
}
seed = hash_combine(seed, offset_order);
seed = hash_combine(seed, direction);
seed = hash_combine(seed, cell.empty());
return seed;
}
protected:
std::vector<std::reference_wrapper<const primitive_id>> get_dependencies() const override {
std::vector<std::reference_wrapper<const primitive_id>> ret;
@@ -79,6 +79,18 @@ struct lstm_dynamic : public primitive_base<lstm_dynamic> {
/// @brief Couple the input and forget gates if input_forget is 1. Default is 0.
bool input_forget;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, clip);
seed = hash_combine(seed, input_forget);
seed = hash_combine(seed, last_hidden_state.empty());
seed = hash_combine(seed, last_cell_state.empty());
seed = hash_combine(seed, bias.empty());
seed = hash_combine(seed, initial_hidden.empty());
seed = hash_combine(seed, initial_cell.empty());
return seed;
}
protected:
std::vector<std::reference_wrapper<const primitive_id>> get_dependencies() const override {
std::vector<std::reference_wrapper<const primitive_id>> ret;
@@ -42,6 +42,12 @@ struct lstm_dynamic_input : public primitive_base<lstm_dynamic_input> {
/// @brief Primitive id containing bias data.
primitive_id bias;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, bias.empty());
return seed;
}
protected:
std::vector<std::reference_wrapper<const primitive_id>> get_dependencies() const override {
std::vector<std::reference_wrapper<const primitive_id>> ret;
@@ -68,6 +68,17 @@ struct lstm_dynamic_timeloop
/// @brief Couple the input and forget gates if input_forget is 1. Default is 0.
bool input_forget;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, clip);
seed = hash_combine(seed, input_forget);
seed = hash_combine(seed, last_hidden_state.empty());
seed = hash_combine(seed, last_cell_state.empty());
seed = hash_combine(seed, initial_hidden.empty());
seed = hash_combine(seed, initial_cell.empty());
return seed;
}
protected:
std::vector<std::reference_wrapper<const primitive_id>> get_dependencies() const override {
std::vector<std::reference_wrapper<const primitive_id>> ret;
@@ -118,6 +118,21 @@ struct matrix_nms : public primitive_base<matrix_nms> {
attributes attribs;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, attribs.sort_type);
seed = hash_combine(seed, attribs.sort_result_across_batch);
seed = hash_combine(seed, attribs.score_threshold);
seed = hash_combine(seed, attribs.nms_top_k);
seed = hash_combine(seed, attribs.keep_top_k);
seed = hash_combine(seed, attribs.background_class);
seed = hash_combine(seed, attribs.decay);
seed = hash_combine(seed, attribs.gaussian_sigma);
seed = hash_combine(seed, attribs.post_threshold);
seed = hash_combine(seed, attribs.normalized);
return seed;
}
private:
static cldnn::matrix_nms::decay_function from(ngraph::op::v8::MatrixNms::DecayFunction decay) {
switch (decay) {
@@ -125,6 +125,22 @@ struct multiclass_nms : public primitive_base<multiclass_nms> {
attributes attrs;
bool has_roisnum{false};
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, has_roisnum);
seed = hash_combine(seed, attrs.background_class);
seed = hash_combine(seed, attrs.indices_output_type);
seed = hash_combine(seed, attrs.iou_threshold);
seed = hash_combine(seed, attrs.keep_top_k);
seed = hash_combine(seed, attrs.nms_eta);
seed = hash_combine(seed, attrs.nms_top_k);
seed = hash_combine(seed, attrs.normalized);
seed = hash_combine(seed, attrs.score_threshold);
seed = hash_combine(seed, attrs.sort_result);
seed = hash_combine(seed, attrs.sort_result_across_batch);
return seed;
}
protected:
std::vector<std::reference_wrapper<const primitive_id>> get_dependencies() const override {
std::vector<std::reference_wrapper<const primitive_id>> ret;
@@ -47,5 +47,11 @@ struct mutable_data : public primitive_base<mutable_data> {
/// @brief Specifies function which will be used to fill weights.
filler_type fill_type;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, id);
return seed;
}
};
} // namespace cldnn
@@ -40,5 +40,14 @@ struct mvn : public primitive_base<mvn> {
bool eps_inside_sqrt;
/// @brief Determines if the normalization is done across or within channels.
bool across_channels;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, normalize_variance);
seed = hash_combine(seed, epsilon);
seed = hash_combine(seed, eps_inside_sqrt);
seed = hash_combine(seed, across_channels);
return seed;
}
};
} // namespace cldnn
@@ -63,6 +63,19 @@ struct non_max_suppression : public primitive_base<non_max_suppression> {
primitive_id second_output;
primitive_id third_output;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, center_point_box);
seed = hash_combine(seed, sort_result_descending);
seed = hash_combine(seed, num_select_per_class.empty());
seed = hash_combine(seed, iou_threshold.empty());
seed = hash_combine(seed, score_threshold.empty());
seed = hash_combine(seed, soft_nms_sigma.empty());
seed = hash_combine(seed, second_output.empty());
seed = hash_combine(seed, third_output.empty());
return seed;
}
std::vector<std::reference_wrapper<const primitive_id>> get_dependencies() const override {
std::vector<std::reference_wrapper<const primitive_id>> ret;
if (!num_select_per_class.empty())
@@ -55,6 +55,13 @@ struct normalize : public primitive_base<normalize> {
/// @brief Epsilon for not dividing by zero while normalizing.
float epsilon;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, across_spatial);
seed = hash_combine(seed, epsilon);
return seed;
}
protected:
std::vector<std::reference_wrapper<const primitive_id>> get_dependencies() const override { return {scale_input}; }
};
@@ -87,5 +87,13 @@ struct one_hot : public primitive_base<one_hot> {
float on_value;
/// @brief all other locations take value this value.
float off_value;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, one_hot_axis);
seed = hash_combine(seed, on_value);
seed = hash_combine(seed, off_value);
return seed;
}
};
} // namespace cldnn
@@ -31,5 +31,11 @@ struct permute : public primitive_base<permute> {
/// @brief Array of permuted output order in bfyx format.
std::vector<uint16_t> permute_order;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_range(seed, permute_order.begin(), permute_order.end());
return seed;
}
};
} // namespace cldnn
@@ -159,6 +159,23 @@ struct pooling : public primitive_base<pooling> {
data_types index_element_type = data_types::i32;
bool maxPoolOpset8Features{false};
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, mode);
seed = hash_range(seed, size.begin(), size.end());
seed = hash_range(seed, stride.begin(), stride.end());
seed = hash_range(seed, pads_begin.begin(), pads_begin.end());
seed = hash_range(seed, dilation.begin(), dilation.end());
seed = hash_range(seed, pads_end.begin(), pads_end.end());
seed = hash_combine(seed, auto_pad);
seed = hash_combine(seed, rounding_type);
seed = hash_combine(seed, axis);
seed = hash_combine(seed, index_element_type);
seed = hash_combine(seed, maxPoolOpset8Features);
seed = hash_combine(seed, indices_output.empty());
return seed;
}
protected:
std::vector<std::reference_wrapper<const primitive_id>> get_dependencies() const override {
std::vector<std::reference_wrapper<const primitive_id>> ret;
@@ -85,6 +85,23 @@ public:
virtual primitive_id type_string() const = 0;
virtual size_t hash() const {
size_t seed = 0;
// hash for type
primitive_id type_str = type_string();
for (size_t idx = 0; idx < type_str.size(); idx++) {
seed = hash_combine(seed, type_str[idx]);
}
// hash for number of outputs
seed = hash_combine(seed, num_outputs);
// hash for number of inputs
auto inputs = dependencies();
seed = hash_combine(seed, inputs.size());
return seed;
}
/// @brief Implicit conversion to primiitive id.
operator primitive_id() const { return id; }
@@ -172,6 +172,39 @@ struct prior_box : public primitive_base<prior_box> {
bool is_clustered() const { return clustered; }
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, img_size.spatial[0]);
seed = hash_combine(seed, img_size.spatial[1]);
seed = hash_range(seed, min_sizes.begin(), min_sizes.end());
seed = hash_range(seed, max_sizes.begin(), max_sizes.end());
seed = hash_range(seed, aspect_ratios.begin(), aspect_ratios.end());
seed = hash_combine(seed, flip);
seed = hash_combine(seed, clip);
seed = hash_range(seed, variance.begin(), variance.end());
seed = hash_combine(seed, step_width);
seed = hash_combine(seed, step_height);
seed = hash_combine(seed, offset);
seed = hash_combine(seed, scale_all_sizes);
seed = hash_range(seed, fixed_ratio.begin(), fixed_ratio.end());
seed = hash_range(seed, fixed_size.begin(), fixed_size.end());
seed = hash_range(seed, density.begin(), density.end());
seed = hash_combine(seed, support_opset8);
seed = hash_combine(seed, step);
seed = hash_combine(seed, min_max_aspect_ratios_order);
seed = hash_range(seed, widths.begin(), widths.end());
seed = hash_range(seed, heights.begin(), heights.end());
seed = hash_combine(seed, clustered);
return seed;
}
private:
bool clustered;
@@ -165,6 +165,31 @@ struct proposal : public primitive_base<proposal> {
bool round_ratios;
bool shift_anchors;
bool normalize;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, max_proposals);
seed = hash_combine(seed, iou_threshold);
seed = hash_combine(seed, base_bbox_size);
seed = hash_combine(seed, min_bbox_size);
seed = hash_combine(seed, feature_stride);
seed = hash_combine(seed, pre_nms_topn);
seed = hash_combine(seed, post_nms_topn);
seed = hash_range(seed, ratios.begin(), ratios.end());
seed = hash_range(seed, scales.begin(), scales.end());
seed = hash_combine(seed, coordinates_offset);
seed = hash_combine(seed, box_coordinate_scale);
seed = hash_combine(seed, box_size_scale);
seed = hash_combine(seed, for_deformable);
seed = hash_combine(seed, swap_xy);
seed = hash_combine(seed, initial_clip);
seed = hash_combine(seed, clip_before_nms);
seed = hash_combine(seed, clip_after_nms);
seed = hash_combine(seed, round_ratios);
seed = hash_combine(seed, shift_anchors);
seed = hash_combine(seed, normalize);
return seed;
}
};
} // namespace cldnn
@@ -58,5 +58,13 @@ struct pyramid_roi_align : public primitive_base<pyramid_roi_align> {
int sampling_ratio;
std::vector<int> pyramid_scales;
int pyramid_starting_level;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, sampling_ratio);
seed = hash_range(seed, pyramid_scales.begin(), pyramid_scales.end());
seed = hash_combine(seed, pyramid_starting_level);
return seed;
}
};
} // namespace cldnn
@@ -30,5 +30,11 @@ struct quantize : public primitive_base<quantize> {
/// @brief levels The number of quantization levels.
int levels;
size_t hash() const override {
size_t seed = primitive::hash();
seed = cldnn::hash_combine(seed, levels);
return seed;
}
};
} // namespace cldnn
@@ -42,6 +42,13 @@ struct random_uniform : public primitive_base<random_uniform> {
const uint64_t op_seed;
const tensor output_shape;
const format output_format;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, global_seed);
seed = hash_combine(seed, op_seed);
return seed;
}
};
} // namespace cldnn
@@ -60,5 +60,13 @@ struct reduce : public primitive_base<reduce> {
std::vector<int64_t> axes;
/// @brief Keep the reduced dimension or not, 1 mean keep reduced dimension
bool keep_dims;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, mode);
seed = hash_range(seed, axes.begin(), axes.end());
seed = hash_combine(seed, keep_dims);
return seed;
}
};
} // namespace cldnn
@@ -41,6 +41,16 @@ struct region_yolo : public primitive_base<region_yolo> {
uint32_t num;
uint32_t mask_size;
bool do_softmax;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, coords);
seed = hash_combine(seed, classes);
seed = hash_combine(seed, num);
seed = hash_combine(seed, mask_size);
seed = hash_combine(seed, do_softmax);
return seed;
}
};
} // namespace cldnn
#pragma once
@@ -155,6 +155,16 @@ struct reorder : public primitive_base<reorder> {
/// @brief Convert truncation Mode
bool truncate = false;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, mean_mode);
seed = hash_combine(seed, input_mem_type);
seed = hash_combine(seed, truncate);
seed = hash_range(seed, subtract_per_feature.begin(), subtract_per_feature.end());
seed = hash_combine(seed, mean.empty());
return seed;
}
protected:
std::vector<std::reference_wrapper<const primitive_id>> get_dependencies() const override {
if (mean.empty())
@@ -28,6 +28,12 @@ struct reorg_yolo : public primitive_base<reorg_yolo> {
/// @details
/// Specific behaviour is determined by these parameters, as follows:
uint32_t stride;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, stride);
return seed;
}
};
} // namespace cldnn
#pragma once
@@ -149,5 +149,21 @@ struct resample : public primitive_base<resample> {
InterpolateOp::CoordinateTransformMode coord_trans_mode;
/// @param round_mode specifies round mode when mode == nearest and is used only when mode == nearest.
InterpolateOp::NearestMode round_mode;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, num_filter);
seed = hash_range(seed, scales.begin(), scales.end());
seed = hash_range(seed, axes.begin(), axes.end());
seed = hash_range(seed, pads_begin.begin(), pads_begin.end());
seed = hash_range(seed, pads_end.begin(), pads_end.end());
seed = hash_combine(seed, operation_type);
seed = hash_combine(seed, shape_calc_mode);
seed = hash_combine(seed, antialias);
seed = hash_combine(seed, cube_coeff);
seed = hash_combine(seed, coord_trans_mode);
seed = hash_combine(seed, round_mode);
return seed;
}
};
} // namespace cldnn
@@ -27,5 +27,11 @@ struct reverse : public primitive_base<reverse> {
mode{mode} {}
reverse_mode mode{reverse_mode::index};
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, mode);
return seed;
}
};
} // namespace cldnn
@@ -51,5 +51,12 @@ struct reverse_sequence : public primitive_base<reverse_sequence> {
int32_t seq_axis;
/// @brief The axis along which reversal is performed.
int32_t batch_axis;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, seq_axis);
seed = hash_combine(seed, batch_axis);
return seed;
}
};
} // namespace cldnn
@@ -59,5 +59,14 @@ struct roi_align : public primitive_base<roi_align> {
PoolingMode pooling_mode;
/// @brief Method to coordinate alignment.
AlignedMode aligned_mode;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, sampling_ratio);
seed = hash_combine(seed, spatial_scale);
seed = hash_combine(seed, pooling_mode);
seed = hash_combine(seed, aligned_mode);
return seed;
}
};
} // namespace cldnn
@@ -80,6 +80,22 @@ struct roi_pooling : public primitive_base<roi_pooling> {
int group_size;
int spatial_bins_x;
int spatial_bins_y;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, mode);
seed = hash_combine(seed, position_sensitive);
seed = hash_combine(seed, pooled_width);
seed = hash_combine(seed, pooled_height);
seed = hash_combine(seed, spatial_scale);
seed = hash_combine(seed, trans_std);
seed = hash_combine(seed, no_trans);
seed = hash_combine(seed, part_size);
seed = hash_combine(seed, group_size);
seed = hash_combine(seed, spatial_bins_x);
seed = hash_combine(seed, spatial_bins_y);
return seed;
}
};
} // namespace cldnn
@@ -26,6 +26,12 @@ struct roll : primitive_base<roll> {
/// @brief Tensor which specifies the number of places by which the elements are shifted.
tensor shift;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, shift.hash());
return seed;
}
};
} // namespace cldnn
@@ -28,5 +28,11 @@ struct scatter_elements_update : public primitive_base<scatter_elements_update>
/// @brief ScatterElementsUpdate axis
int64_t axis;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, axis);
return seed;
}
};
} // namespace cldnn
@@ -28,5 +28,11 @@ struct scatter_nd_update : public primitive_base<scatter_nd_update> {
/// @brief ScatterNDUpdate indices_rank
size_t indices_rank;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, indices_rank);
return seed;
}
};
} // namespace cldnn
@@ -37,5 +37,11 @@ struct scatter_update : public primitive_base<scatter_update> {
/// @brief ScatterUpdate axis
int64_t axis;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, axis);
return seed;
}
};
} // namespace cldnn
@@ -29,5 +29,12 @@ struct shuffle_channels : public primitive_base<shuffle_channels> {
int32_t group;
/// @brief The index of the channel dimension (default is 1).
int32_t axis;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, group);
seed = hash_combine(seed, axis);
return seed;
}
};
} // namespace cldnn
@@ -38,5 +38,11 @@ struct softmax : public primitive_base<softmax> {
/// - when softmax dimension is set to 3 (x dim) each input row is normalized independently.
int64_t dimension;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, dimension);
return seed;
}
};
} // namespace cldnn
@@ -60,5 +60,13 @@ struct space_to_batch : public primitive_base<space_to_batch> {
tensor pads_begin;
tensor pads_end;
tensor out_size;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, block_shape.hash());
seed = hash_combine(seed, pads_begin.hash());
seed = hash_combine(seed, pads_end.hash());
return seed;
}
};
} // namespace cldnn
@@ -64,5 +64,12 @@ struct space_to_depth : public primitive_base<space_to_depth> {
/// @brief Block size.
size_t block_size;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, mode);
seed = hash_combine(seed, block_size);
return seed;
}
};
} // namespace cldnn
@@ -49,6 +49,14 @@ struct split : public primitive_base<split> {
/// @brief List of output_ids.
const primitive_id_arr output_ids;
size_t hash() const override {
size_t seed = primitive::hash();
for (auto& offset : output_offsets) {
seed = hash_combine(seed, offset.hash());
}
return seed;
}
protected:
static std::vector<primitive_id> extract_primitive_vector(
const std::vector<std::pair<primitive_id, tensor> >& stor) {
@@ -102,5 +102,14 @@ struct strided_slice : public primitive_base<strided_slice> {
std::vector<int64_t> ellipsis_mask;
/// @brief Size of output tensor
ov::Shape out_size;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_range(seed, begin_mask.begin(), begin_mask.end());
seed = hash_range(seed, end_mask.begin(), end_mask.end());
seed = hash_range(seed, new_axis_mask.begin(), new_axis_mask.end());
seed = hash_range(seed, shrink_axis_mask.begin(), shrink_axis_mask.end());
return seed;
}
};
} // namespace cldnn
@@ -32,5 +32,11 @@ struct tile : public primitive_base<tile> {
/// @brief A per-dimension replication factor
std::vector<int64_t> repeats;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_range(seed, repeats.begin(), repeats.end());
return seed;
}
};
} // namespace cldnn
@@ -332,6 +332,14 @@ struct padding {
return padding{lower.sizes(), upper.sizes(), filling_value};
}
size_t hash() const {
size_t seed = 0;
seed = cldnn::hash_combine(seed, _filling_value);
seed = cldnn::hash_combine(seed, _lower_size.hash());
seed = cldnn::hash_combine(seed, _upper_size.hash());
return seed;
}
private:
tensor _lower_size; ///< Lower padding sizes. For spatials, it means size of left (X) and top (Y) padding.
tensor _upper_size; ///< Upper padding sizes. For spatials, it means size of right (X) and bottom (Y) padding.
@@ -511,6 +519,19 @@ struct layout {
ov::PartialShape transform(cldnn::format new_fmt) const;
size_t hash() const {
size_t seed = 0;
seed = hash_combine(seed, data_padding.hash());
seed = hash_combine(seed, format.value);
seed = hash_combine(seed, data_type);
auto pshape = get_partial_shape();
for (size_t idx = 0; idx < pshape.size(); idx++) {
seed = hash_combine(seed, pshape[idx].get_length());
}
return seed;
}
private:
/// The size of the @ref memory (excluding padding)
ov::PartialShape size;
@@ -165,5 +165,5 @@ private:
};
using ImplementationsCache = cldnn::LruCache<size_t, std::shared_ptr<primitive_impl>>;
using KernelsCache = cldnn::LruCache<std::string, cldnn::kernel::ptr>;
using KernelsCache = cldnn::LruCache<size_t, cldnn::kernel::ptr>;
} // namespace cldnn
@@ -318,6 +318,15 @@ public:
return os;
}
size_t hash() const {
size_t seed = 0;
seed = hash_range(seed, batch.begin(), batch.end());
seed = hash_range(seed, feature.begin(), feature.end());
seed = hash_range(seed, spatial.begin(), spatial.end());
seed = hash_range(seed, group.begin(), group.end());
return seed;
}
std::string to_string() const {
std::stringstream out;
const char* delim = "";
@@ -12,6 +12,7 @@
#include <algorithm>
#include <sstream>
#include <vector>
#include <set>
namespace cldnn {
@@ -194,6 +195,14 @@ static size_t hash_combine(size_t seed, const T &v) {
return hash_combine(seed, static_cast<underlying_t>(v));
}
template <class It>
static size_t hash_range(size_t seed, It first, It last) {
for (; first != last; ++first) {
seed = hash_combine(seed, *first);
}
return seed;
}
/// @}
/// @endcond
/// @}
@@ -7,19 +7,55 @@
#include "kernel_selector/kernel_base.h"
namespace cldnn {
class CompilationTaskQueue {
using CompilationTaskData = std::pair<size_t, ICompilationContext::Task>;
public:
void push_task(size_t task_key, ICompilationContext::Task&& task) {
std::lock_guard<std::mutex> lock(_mutex);
if (_queue_keymap.find(task_key) == _queue_keymap.end()) {
auto insert_it = _queue.insert(_queue.end(), {task_key, task});
_queue_keymap.insert({task_key, insert_it});
}
}
bool pop_front_task(size_t& task_key, ICompilationContext::Task& task) {
std::lock_guard<std::mutex> lock(_mutex);
if (!_queue.empty()) {
auto front = _queue.front();
task = front.second;
task_key = front.first;
_queue.pop_front();
return true;
}
return false;
}
void erase_task_key(size_t removed_key) {
std::lock_guard<std::mutex> lock(_mutex);
if (_queue_keymap.find(removed_key) != _queue_keymap.end()) {
_queue_keymap.erase(removed_key);
}
}
private:
std::deque<CompilationTaskData> _queue;
std::unordered_map<size_t, std::deque<CompilationTaskData>::iterator> _queue_keymap;
std::mutex _mutex;
};
class CompilationContext : public ICompilationContext {
public:
using compilation_queue_t = InferenceEngine::ThreadSafeQueue<ICompilationContext::Task>;
CompilationContext(cldnn::engine& engine, const ExecutionConfig& config, size_t program_id) {
_kernels_cache = cldnn::make_unique<kernels_cache>(engine, config, program_id, nullptr, kernel_selector::KernelBase::get_db().get_batch_header_str());
_worker = std::thread([this](){
while (!_stop_compilation) {
CompilationContext::Task task;
bool success = _queue.try_pop(task);
size_t task_key;
bool success = _queue.pop_front_task(task_key, task);
if (success) {
task(*_kernels_cache);
_queue.erase_task_key(task_key);
} else {
std::chrono::milliseconds ms{1};
std::this_thread::sleep_for(ms);
@@ -28,8 +64,8 @@ public:
});
}
void push_task(ICompilationContext::Task&& task) override {
_queue.push(task);
void push_task(size_t key, ICompilationContext::Task&& task) override {
_queue.push_task(key, std::move(task));
}
void cancel() noexcept override {
@@ -42,9 +78,10 @@ public:
private:
std::unique_ptr<kernels_cache> _kernels_cache;
compilation_queue_t _queue;
std::thread _worker;
std::atomic_bool _stop_compilation{false};
CompilationTaskQueue _queue;
};
std::unique_ptr<ICompilationContext> ICompilationContext::create(cldnn::engine& engine, const ExecutionConfig& config, size_t program_id) {
@@ -34,6 +34,7 @@ struct condition_impl : typed_primitive_impl<condition> {
a->wait();
}
auto ev = instance.get_network().get_stream().create_user_event(false);
set_node_params(instance.get_node());
bool exec_branch = choose_branch_to_exec(instance);
memory::ptr memory_to_copy;
@@ -13,7 +13,7 @@ namespace cldnn {
class ICompilationContext {
public:
using Task = std::function<void(kernels_cache&)>;
virtual void push_task(Task&& task) = 0;
virtual void push_task(size_t key, Task&& task) = 0;
virtual void cancel() noexcept = 0;
virtual ~ICompilationContext() = default;
@@ -107,6 +107,11 @@ public:
return params;
}
void calculate_hash() override {
parent::calculate_hash();
seed = hash_combine(seed, transposed);
}
private:
bool transposed;
uint32_t groups;
@@ -36,6 +36,12 @@ struct generic_layer : public primitive_base<generic_layer> {
layout output_layout;
const kernel_selector::generic_kernel_params generic_params;
size_t hash() const override {
size_t seed = primitive::hash();
seed = hash_combine(seed, id);
return seed;
}
protected:
std::vector<std::reference_wrapper<const primitive_id>> get_dependencies() const override { return {}; }
};
@@ -214,6 +214,9 @@ public:
virtual void update_output_memory() {}
virtual size_t get_impl_key(const kernel_impl_params& params) const;
virtual size_t get_impl_key() const;
protected:
primitive_inst(network& network, program_node const& node, bool allocate_memory);
@@ -291,7 +294,8 @@ protected:
virtual void update_shape();
virtual event::ptr update_weights();
void update_impl();
// if primitive_inst doesn't replace impl to new impl(static impl with opt kerenl or dynamic impl), return false
bool update_impl();
void realloc_if_needed();
cldnn::network::ptr get_unfused_subgraph();
@@ -370,6 +370,9 @@ public:
void set_preferred_input_fmt(size_t idx, format::type type);
void set_preferred_output_fmt(size_t idx, format::type type);
virtual void calculate_hash() {}
size_t get_hash() const { return seed; }
protected:
size_t unique_id = 0;
@@ -411,6 +414,8 @@ protected:
void invalidate_users() const;
size_t seed = 0;
private:
#ifdef ENABLE_ONEDNN_FOR_GPU
std::vector<fused_primitive_desc_onednn> fused_prims_onednn;
@@ -454,6 +459,16 @@ public:
return std::static_pointer_cast<const PType>(program_node::get_primitive());
}
void calculate_hash() override {
// hash for primitive
seed = get_primitive()->hash();
// hash for fused prims
for (auto& prim : fused_prims) {
seed = hash_combine(seed, prim.desc->hash());
}
}
protected:
std::shared_ptr<PType> typed_desc() const { return std::static_pointer_cast<PType>(desc); }
};
@@ -97,6 +97,34 @@ public:
}
std::vector<size_t> get_shape_infer_dependencies() const override { return {}; }
void calculate_hash() override {
parent::calculate_hash();
seed = hash_combine(seed, scale_shift_opt);
seed = hash_combine(seed, need_post_scale);
seed = hash_combine(seed, need_post_shift);
seed = hash_combine(seed, need_pre_shift);
seed = hash_combine(seed, need_clamp);
seed = hash_combine(seed, need_min_clamp);
seed = hash_combine(seed, need_max_clamp);
seed = hash_combine(seed, per_tensor_input_range);
seed = hash_combine(seed, per_tensor_input_scale);
seed = hash_combine(seed, per_tensor_input_shift);
seed = hash_combine(seed, per_tensor_output_range);
seed = hash_combine(seed, per_tensor_output_scale);
seed = hash_combine(seed, per_tensor_output_shift);
seed = hash_combine(seed, in_lo);
seed = hash_combine(seed, in_hi);
seed = hash_combine(seed, in_scale);
seed = hash_combine(seed, in_shift);
seed = hash_combine(seed, out_lo);
seed = hash_combine(seed, out_hi);
seed = hash_combine(seed, out_scale);
seed = hash_combine(seed, out_shift);
}
private:
inline float clamp(float val) const {
return std::max(std::numeric_limits<float>::lowest(), std::min(std::numeric_limits<float>::max(), val));
@@ -284,28 +284,10 @@ void primitive_inst::realloc_if_needed() {
}
}
void primitive_inst::update_impl() {
bool primitive_inst::update_impl() {
GPU_DEBUG_PROFILED_STAGE(instrumentation::pipeline_stage::update_implementation);
auto prev_impl_str = _impl != nullptr ? _impl->get_kernel_name() : "nullptr";
auto get_layout_key = [&](const kernel_impl_params& params) -> size_t {
size_t seed = 0;
auto& id = params.desc->id;
for (size_t i = 0; i < id.size(); i++) {
seed = hash_combine(seed, id[i]);
}
seed = hash_combine(seed, _node->get_unique_id());
for (auto& layout : params.input_layouts) {
for (auto& d : layout.get_shape()) {
seed = hash_combine(seed, d);
}
}
for (auto& d : params.get_output_layout().get_shape()) {
seed = hash_combine(seed, d);
}
return seed;
};
auto update_shape_info = [this, prev_impl_str](const kernel_impl_params& params) {
mem_lock<int32_t> lock(_shape_info_memory, _network.get_stream());
size_t offset = 0;
@@ -334,28 +316,31 @@ void primitive_inst::update_impl() {
if (!_node->is_type<data>() && !(_node->is_type<mutable_data>() && _node->get_dependencies().empty())) {
// Update param if fake_alignment is available
auto updated_params = _node->type()->get_fake_aligned_params(*_impl_params);
auto layout_key = get_layout_key(updated_params);
auto impl_key = get_impl_key(updated_params);
auto& cache = get_network().get_implementations_cache();
bool has_cached_impl = false;
{
std::lock_guard<std::mutex> lock(get_network().get_impl_cache_mutex());
has_cached_impl = cache.has(layout_key);
has_cached_impl = cache.has(impl_key);
if (has_cached_impl) {
_impl = cache.get(layout_key)->clone();
_impl = cache.get(impl_key)->clone();
GPU_DEBUG_PROFILED_STAGE_CACHE_HIT(true);
GPU_DEBUG_TRACE_DETAIL << id() << ": get impl from cache " << _impl->get_kernel_name() << std::endl;
// impl is not replaced
} else if (!shape_changed() && _impl != nullptr && _impl->is_dynamic()) {
return false;
}
}
if (!has_cached_impl) {
if (_dynamic_impl) {
auto& compilation_context = get_network().get_compilation_context();
compilation_context.push_task([this, updated_params, layout_key](kernels_cache& kc) {
compilation_context.push_task(impl_key, [this, updated_params, impl_key](kernels_cache& kc) {
auto& cache = get_network().get_implementations_cache();
{
std::lock_guard<std::mutex> lock(get_network().get_impl_cache_mutex());
// Check existense in the cache one more time as several iterations of model execution could happens and multiple compilation
// tasks created for same shapes
if (cache.has(layout_key))
if (cache.has(impl_key))
return;
}
@@ -367,7 +352,7 @@ void primitive_inst::update_impl() {
kc.reset();
std::lock_guard<std::mutex> lock(get_network().get_impl_cache_mutex());
cache.add(layout_key, impl->clone());
cache.add(impl_key, impl->clone());
});
_impl = _dynamic_impl->clone();
@@ -383,7 +368,7 @@ void primitive_inst::update_impl() {
_impl->init_kernels(kernels_cache);
kernels_cache.reset();
std::lock_guard<std::mutex> lock(get_network().get_impl_cache_mutex());
cache.add(layout_key, _impl->clone());
cache.add(impl_key, _impl->clone());
auto new_impl_str = _impl != nullptr ? _impl->get_kernel_name() : "nullptr";
GPU_DEBUG_TRACE_DETAIL << id() << ": update impl from " << prev_impl_str << " to " << new_impl_str << std::endl;
@@ -392,6 +377,8 @@ void primitive_inst::update_impl() {
reset_shape_change();
}
// impl is replaced
return true;
}
event::ptr primitive_inst::execute(const std::vector<event::ptr>& events) {
@@ -432,12 +419,16 @@ event::ptr primitive_inst::execute(const std::vector<event::ptr>& events) {
return outputs.at(last_prim_id).get_event();
}
if (shape_changed() || !_impl) {
update_impl();
auto ev = update_weights();
if (ev)
dependencies.push_back(ev);
realloc_if_needed();
// Try update impl if current impl is dynamic because opt kernel may be added to impl cache through async compilation.
// Only try update weight and realloc when impl is updated.
if (shape_changed() || !_impl
|| (!shape_changed() && _impl->is_dynamic())) {
if (update_impl()) {
auto ev = update_weights();
if (ev)
dependencies.push_back(ev);
realloc_if_needed();
}
}
}
@@ -697,32 +688,30 @@ event::ptr primitive_inst::update_weights() {
layout expected_layout = from_weights_tensor(weights_params.dest);
auto& engine = _network.get_engine();
auto get_layout_key = [&]() -> std::string {
std::string layout_key_str = id() + "_" + std::to_string(_node->get_unique_id());
layout_key_str += "_" + expected_layout.to_string();
layout_key_str += "_" + original_layout.to_string();
return layout_key_str;
auto get_kernel_key = [&]() -> size_t {
auto seed = _node->get_hash();
seed = hash_combine(seed, expected_layout.hash());
seed = hash_combine(seed, original_layout.hash());
return seed;
};
cldnn::kernel::ptr kernel = nullptr;
auto layout_key = get_layout_key();
if (layout_key != "") {
auto& cache = get_network().get_in_mem_kernels_cache();
if (cache.has(layout_key)) {
GPU_DEBUG_TRACE_DETAIL << id() << ": reorder weights (cached) from " << original_layout.to_short_string()
<< " to " << expected_layout.to_short_string() << std::endl;
GPU_DEBUG_PROFILED_STAGE_CACHE_HIT(true);
kernel = cache.get(layout_key);
} else {
GPU_DEBUG_TRACE_DETAIL << id() << ": reorder weights from " << original_layout.to_short_string()
<< " to " << expected_layout.to_short_string() << std::endl;
auto& kernels_cache = get_network().get_kernels_cache();
auto kernel_id = kernels_cache.set_kernel_source(weights_params.clKernel->code.kernelString, false);
kernels_cache.compile();
kernel = kernels_cache.get_kernel(kernel_id);
cache.add(layout_key, kernel);
kernels_cache.reset();
}
auto kernel_key = get_kernel_key();
auto& cache = get_network().get_in_mem_kernels_cache();
if (cache.has(kernel_key)) {
GPU_DEBUG_TRACE_DETAIL << id() << ": reorder weights (cached) from " << original_layout.to_short_string()
<< " to " << expected_layout.to_short_string() << std::endl;
GPU_DEBUG_PROFILED_STAGE_CACHE_HIT(true);
kernel = cache.get(kernel_key);
} else {
GPU_DEBUG_TRACE_DETAIL << id() << ": reorder weights from " << original_layout.to_short_string()
<< " to " << expected_layout.to_short_string() << std::endl;
auto& kernels_cache = get_network().get_kernels_cache();
auto kernel_id = kernels_cache.set_kernel_source(weights_params.clKernel->code.kernelString, false);
kernels_cache.compile();
kernel = kernels_cache.get_kernel(kernel_id);
cache.add(kernel_key, kernel);
kernels_cache.reset();
}
auto& stream = get_network().get_stream();
@@ -1269,4 +1258,20 @@ void primitive_inst::load(cldnn::BinaryInputBuffer& ib) {
ib >> _impl;
}
}
size_t primitive_inst::get_impl_key(const kernel_impl_params& params) const {
size_t seed = _node->get_hash();
const size_t prime_number = 2654435761; // magic number to avoid hash collision.
for (auto& in : params.input_layouts) {
seed = hash_combine(seed, in.hash() * prime_number);
}
for (auto& out : params.output_layouts) {
seed = hash_combine(seed, out.hash() * prime_number);
}
return seed;
}
size_t primitive_inst::get_impl_key() const {
auto updated_params = _node->type()->get_fake_aligned_params(*_impl_params);
return get_impl_key(updated_params);
}
} // namespace cldnn
@@ -127,6 +127,7 @@ program::program(engine& engine_ref,
} else {
build_program(is_internal);
}
calc_nodes_hash();
}
program::program(engine& engine_ref,
@@ -151,6 +152,7 @@ program::program(engine& engine_ref,
pm = std::unique_ptr<pass_manager>(new pass_manager(*this));
prepare_nodes(nodes);
build_program(is_internal);
calc_nodes_hash();
}
program::program(engine& engine)
@@ -539,6 +541,12 @@ void program::query_local_block_io_supported() {
}
}
void program::calc_nodes_hash() {
for (auto& node : processing_order) {
node->calculate_hash();
}
}
void program::build_program(bool is_internal) {
init_graph();
{ pre_optimize_graph(is_internal); }
@@ -0,0 +1,292 @@
// Copyright (C) 2023-2023 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include <cstddef>
#include "test_utils.h"
#include <intel_gpu/primitives/eltwise.hpp>
#include <intel_gpu/primitives/fully_connected.hpp>
#include <intel_gpu/primitives/crop.hpp>
#include <intel_gpu/primitives/gather.hpp>
#include <intel_gpu/primitives/gemm.hpp>
#include <intel_gpu/primitives/mvn.hpp>
#include <intel_gpu/primitives/permute.hpp>
#include <intel_gpu/primitives/reshape.hpp>
#include "eltwise_inst.h"
// #include "fully_connected_inst.h"
using namespace cldnn;
using namespace tests;
TEST(check_hash_value, eltwise_basic) {
auto& engine = get_test_engine();
auto input1 = engine.allocate_memory({ data_types::f32, format::bfyx, { 2, 2, 2, 2 } });
auto input2 = engine.allocate_memory({ data_types::f32, format::bfyx, { 2, 2, 2, 2 } });
auto key_prim_id = "eltwise";
topology topology;
topology.add(input_layout("input", input1->get_layout()));
topology.add(input_layout("input2", input2->get_layout()));
topology.add(eltwise(key_prim_id, { input_info("input"), input_info("input2") }, eltwise_mode::sum));
auto prog = program::build_program(engine, topology, ExecutionConfig{});
network net(prog, 0);
const auto prim_inst = net.get_primitive(key_prim_id);
const auto primitve = prim_inst->desc();
const auto& prog_node = net.get_program()->get_node(key_prim_id);
const auto primitive_hash = primitve->hash();
const auto prog_node_hash = prog_node.get_hash();
const auto prim_inst_hash = prim_inst->get_impl_key();
ASSERT_EQ(primitive_hash, 11385140218618178073UL);
ASSERT_EQ(prog_node_hash, 11385140218618178073UL);
ASSERT_EQ(prim_inst_hash, 10460622021476296271UL);
}
TEST(check_hash_value, fc_basic) {
auto& engine = get_test_engine();
const int32_t b = 1, in_f = 128, in_x = 1, in_y = 1, out_f = 65;
auto input_prim = engine.allocate_memory({ data_types::f32, format::bfyx, { b, in_f, in_y, in_x } });
auto weights_prim = engine.allocate_memory({ data_types::f32, format::bfyx, { out_f, in_f, in_y, in_x } });
auto bias_prim = engine.allocate_memory({ data_types::f32, format::bfyx, { 1, 1, out_f, 1 } });
auto key_prim_id = "eltwise";
topology topology(
input_layout("input", input_prim->get_layout()),
data("weights", weights_prim),
data("bias", bias_prim),
fully_connected(key_prim_id, input_info("input"), "weights", "bias")
);
auto prog = program::build_program(engine, topology, ExecutionConfig{});
network net(prog, 0);
const auto prim_inst = net.get_primitive(key_prim_id);
const auto primitve = prim_inst->desc();
const auto& prog_node = net.get_program()->get_node(key_prim_id);
const auto primitive_hash = primitve->hash();
const auto prog_node_hash = prog_node.get_hash();
const auto prim_inst_hash = prim_inst->get_impl_key();
ASSERT_EQ(primitive_hash, 7881065839556591629UL);
ASSERT_EQ(prog_node_hash, 7881065839556591629UL);
ASSERT_EQ(prim_inst_hash, 2803059017090178132UL);
}
TEST(check_hash_value, gather_basic) {
auto& engine = get_test_engine();
auto input1 = engine.allocate_memory({ data_types::f16, format::bfzyx, tensor{ 3, 2, 2, 4, 3} }); // Dictionary
auto input2 = engine.allocate_memory({ data_types::f32, format::bfyx, tensor{ 3, 2, 1, 3 } }); // Indexes
int64_t axis = 3;
int64_t batch_dim = -1;
bool negative_indexes = true;
auto key_prim_id = "gather";
topology topology;
topology.add(input_layout("InputDictionary", input1->get_layout()));
topology.add(input_layout("InputText", input2->get_layout()));
topology.add(
gather(key_prim_id, input_info("InputDictionary"), input_info("InputText"), axis, ov::Shape{3, 2, 3, 3, 2}, batch_dim, negative_indexes)
);
auto prog = program::build_program(engine, topology, ExecutionConfig{});
network net(prog, 0);
const auto prim_inst = net.get_primitive(key_prim_id);
const auto primitve = prim_inst->desc();
const auto& prog_node = net.get_program()->get_node(key_prim_id);
const auto primitive_hash = primitve->hash();
const auto prog_node_hash = prog_node.get_hash();
const auto prim_inst_hash = prim_inst->get_impl_key();
ASSERT_EQ(primitive_hash, 93320679543770233UL);
ASSERT_EQ(prog_node_hash, 93320679543770233UL);
ASSERT_EQ(prim_inst_hash, 18126277300376770566UL);
}
TEST(check_hash_value, gemm_basic) {
auto& engine = get_test_engine();
auto input = engine.allocate_memory({ data_types::f32, format::bfyx, { 1, 2, 4, 3 } });
auto input2 = engine.allocate_memory({ data_types::f32, format::bfyx, { 1, 1, 4, 1 } });
auto key_prim_id = "gemm";
topology topology;
topology.add(input_layout("input", input->get_layout()));
topology.add(input_layout("input2", input2->get_layout()));
topology.add(crop("crop.1", input_info("input"), { 1, 1, 4, 3 }, { 0, 1, 0, 0 }));
topology.add(gemm(key_prim_id, { input_info("crop.1"), input_info("input2") }, data_types::f32, false, true));
auto prog = program::build_program(engine, topology, ExecutionConfig{});
network net(prog, 0);
const auto prim_inst = net.get_primitive(key_prim_id);
const auto primitve = prim_inst->desc();
const auto& prog_node = net.get_program()->get_node(key_prim_id);
const auto primitive_hash = primitve->hash();
const auto prog_node_hash = prog_node.get_hash();
const auto prim_inst_hash = prim_inst->get_impl_key();
ASSERT_EQ(primitive_hash, 8009877756431655269UL);
ASSERT_EQ(prog_node_hash, 8009877756431655269UL);
ASSERT_EQ(prim_inst_hash, 2966249915421110547UL);
}
TEST(check_hash_value, permute_basic) {
auto& engine = get_test_engine();
auto input = engine.allocate_memory({ data_types::f32, format::bfyx,{ 2, 2, 3, 2 } });
auto key_prim_id = "permute";
topology topology(
input_layout("input", input->get_layout()),
permute(key_prim_id, input_info("input"), { 0, 1, 2, 3 }));
auto prog = program::build_program(engine, topology, ExecutionConfig{});
network net(prog, 0);
const auto prim_inst = net.get_primitive(key_prim_id);
const auto primitve = prim_inst->desc();
const auto& prog_node = net.get_program()->get_node(key_prim_id);
const auto primitive_hash = primitve->hash();
const auto prog_node_hash = prog_node.get_hash();
const auto prim_inst_hash = prim_inst->get_impl_key();
ASSERT_EQ(primitive_hash, 4658575237077439700UL);
ASSERT_EQ(prog_node_hash, 4658575237077439700UL);
ASSERT_EQ(prim_inst_hash, 4319508487906266226UL);
}
TEST(check_hash_value, reorder_basic) {
auto& engine = get_test_engine();
const int32_t b_in = 1;
const int32_t f_in = 8 * 4;
const int32_t y_in = 4;
const int32_t x_in = 8 * 2;
auto input = engine.allocate_memory({ data_types::f32, format::bfyx, { b_in,f_in,x_in,y_in } });
layout output_layout(data_types::f32, format::b_fs_yx_fsv16, { b_in,f_in,x_in,y_in });
auto key_prim_id = "reorder";
topology topology(
input_layout("input", input->get_layout()),
reorder(key_prim_id, input_info("input"), output_layout));
auto prog = program::build_program(engine, topology, ExecutionConfig{});
network net(prog, 0);
const auto prim_inst = net.get_primitive(key_prim_id);
const auto primitve = prim_inst->desc();
const auto& prog_node = net.get_program()->get_node(key_prim_id);
const auto primitive_hash = primitve->hash();
const auto prog_node_hash = prog_node.get_hash();
const auto prim_inst_hash = prim_inst->get_impl_key();
ASSERT_EQ(primitive_hash, 16293979194373117693UL);
ASSERT_EQ(prog_node_hash, 16293979194373117693UL);
ASSERT_EQ(prim_inst_hash, 1719378641386629286UL);
}
TEST(check_hash_value, reshape_basic) {
auto& engine = get_test_engine();
auto input = engine.allocate_memory({ data_types::f32, format::bfyx, { 1, 1, 2, 2 } });
auto key_prim_id = "reshape";
topology topology;
topology.add(input_layout("input", input->get_layout()));
auto padded_input_layout = input->get_layout();
padded_input_layout.data_padding = padding();
topology.add(reorder("reorder", input_info("input"), padded_input_layout));
topology.add(reshape(key_prim_id, input_info("reorder"), tensor( 1, 1, 4, 1 ), cldnn::reshape::reshape_mode::base, padding({0, 0, 2, 2})));
auto prog = program::build_program(engine, topology, ExecutionConfig{});
network net(prog, 0);
const auto prim_inst = net.get_primitive(key_prim_id);
const auto primitve = prim_inst->desc();
const auto& prog_node = net.get_program()->get_node(key_prim_id);
const auto primitive_hash = primitve->hash();
const auto prog_node_hash = prog_node.get_hash();
const auto prim_inst_hash = prim_inst->get_impl_key();
ASSERT_EQ(primitive_hash, 1534749073560581535UL);
ASSERT_EQ(prog_node_hash, 1534749073560581535UL);
ASSERT_EQ(prim_inst_hash, 1686780870642992006UL);
}
TEST(check_hash_value, conv_basic) {
auto& engine = get_test_engine();
auto input = engine.allocate_memory({ data_types::f32, format::bfzyx, { 1, 1, 4, 4, 4 } });
auto weights = engine.allocate_memory({ data_types::f32, format::bfzyx, { 1, 1, 2, 2, 2 } });
auto biases = engine.allocate_memory({ data_types::f32, format::bfyx, { 1, 1, 1, 1, 1 } });
auto key_prim_id = "convolution";
topology topology(
input_layout("input", input->get_layout()),
data("weights", weights),
data("biases", biases),
convolution(key_prim_id, input_info("input"), { "weights" }, { "biases" }, {1, 1, 1}, {0, 0, 0}, {1, 1, 1}));
auto prog = program::build_program(engine, topology, ExecutionConfig{});
network net(prog, 0);
const auto prim_inst = net.get_primitive(key_prim_id);
const auto primitve = prim_inst->desc();
const auto& prog_node = net.get_program()->get_node(key_prim_id);
const auto primitive_hash = primitve->hash();
const auto prog_node_hash = prog_node.get_hash();
const auto prim_inst_hash = prim_inst->get_impl_key();
ASSERT_EQ(primitive_hash, 12460716932918224126UL);
ASSERT_EQ(prog_node_hash, 14591386802538030726UL);
ASSERT_EQ(prim_inst_hash, 3099955169197623490UL);
}
TEST(check_hash_value, quantize_basic) {
auto& engine = get_test_engine();
auto input = engine.allocate_memory({data_types::f32, format::bfyx, {1, 16, 2, 2}});
auto input_low = engine.allocate_memory({ data_types::f32,format::bfyx,{ 1, 16, 1, 1 } });
auto input_high = engine.allocate_memory({ data_types::f32,format::bfyx,{ 1, 16, 1, 1 } });
auto output_low = engine.allocate_memory({ data_types::f32,format::bfyx,{ 1, 1, 1, 1 } });
auto output_high = engine.allocate_memory({ data_types::f32,format::bfyx,{ 1, 1, 1, 1 } });
auto key_prim_id = "quantize";
topology topology;
topology.add(
input_layout("input", input->get_layout()),
data("input_low", input_low),
data("input_high", input_high),
data("output_low", output_low),
data("output_high", output_high),
quantize(key_prim_id, input_info("input"), input_info("input_low"), input_info("input_high"), input_info("output_low"), input_info("output_high"), 256, data_types::u8)
);
auto prog = program::build_program(engine, topology, ExecutionConfig{});
network net(prog, 0);
const auto prim_inst = net.get_primitive(key_prim_id);
const auto primitve = prim_inst->desc();
const auto& prog_node = net.get_program()->get_node(key_prim_id);
const auto primitive_hash = primitve->hash();
const auto prog_node_hash = prog_node.get_hash();
const auto prim_inst_hash = prim_inst->get_impl_key();
ASSERT_EQ(primitive_hash, 1569171484239412698UL);
ASSERT_EQ(prog_node_hash, 4135863035456568493UL);
ASSERT_EQ(prim_inst_hash, 13898649554943348250UL);
}
@@ -0,0 +1,189 @@
// Copyright (C) 2018-2023 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include <tuple>
#include <string>
#include <vector>
#include <memory>
#include "ngraph_functions/utils/ngraph_helpers.hpp"
#include "ngraph_functions/builders.hpp"
#include "shared_test_classes/base/ov_subgraph.hpp"
#include "shared_test_classes/single_layer/shape_of.hpp"
#include "shared_test_classes/single_layer/strided_slice.hpp"
#include <shared_test_classes/single_layer/eltwise.hpp>
#include <common_test_utils/ov_tensor_utils.hpp>
using namespace ngraph;
using namespace InferenceEngine;
using namespace ov::test;
namespace GPULayerTestsDefinitions {
typedef std::tuple<
std::vector<InputShape>, // input shapes
ElementType, // Network precision
TargetDevice, // Device name
std::map<std::string, std::string> // Additional network configuration
> genImplKeyDynamicGPUTestParamsSet;
const std::vector<ElementType> netPrecisions = {
ElementType::f16,
ElementType::f32,
ElementType::i32,
ElementType::i64,
};
class GenlImplKeyDynamicGPUTest : public testing::WithParamInterface<genImplKeyDynamicGPUTestParamsSet>,
virtual public SubgraphBaseTest {
public:
static std::string getTestCaseName(const testing::TestParamInfo<genImplKeyDynamicGPUTestParamsSet>& obj) {
genImplKeyDynamicGPUTestParamsSet basicParamsSet = obj.param;
std::ostringstream result;
std::vector<InputShape> inputShapes;
ElementType netType;
TargetDevice targetDevice;
std::map<std::string, std::string> additionalConfig;
std::tie(inputShapes, netType, targetDevice, additionalConfig) = basicParamsSet;
result << "IS=";
for (const auto& shape : inputShapes) {
result << CommonTestUtils::partialShape2str({shape.first}) << "_";
for (const auto& actual_shape : shape.second) {
result << CommonTestUtils::partialShape2str({actual_shape}) << "_";
}
}
result << "NetType=" << netType << "_";
result << "targetDevice=" << targetDevice;
return result.str();
}
protected:
void generate_inputs(const std::vector<ngraph::Shape>& targetInputStaticShapes) override {
inputs.clear();
const auto& funcInputs = function->inputs();
for (int i = 0; i < funcInputs.size(); ++i) {
const auto& funcInput = funcInputs[i];
ov::Tensor tensor;
tensor = ov::test::utils::create_and_fill_tensor(funcInput.get_element_type(),
targetInputStaticShapes[i],
80,
0,
8);
inputs.insert({funcInput.get_node_shared_ptr(), tensor});
}
}
void SetUp() override {
genImplKeyDynamicGPUTestParamsSet basicParamsSet = this->GetParam();
std::vector<InputShape> inputShapes;
ElementType netType;
std::map<std::string, std::string> additionalConfig;
std::tie(inputShapes, netType, targetDevice, additionalConfig) = basicParamsSet;
init_input_shapes(inputShapes);
const auto inShapeShapeOf = inputDynamicShapes[0];
const auto inShapeElt = inputDynamicShapes[1];
auto params = builder::makeDynamicParams(netType, {inShapeShapeOf, inShapeElt});
auto paramOuts = helpers::convert2OutputVector(ngraph::helpers::castOps2Nodes<ngraph::opset3::Parameter>(params));
auto addOp1 = ngraph::builder::makeEltwise(paramOuts[1], paramOuts[1], ngraph::helpers::EltwiseTypes::ADD);
addOp1->set_friendly_name("add1");
auto shapeOfOp1 = std::make_shared<ngraph::opset3::ShapeOf>(addOp1, ElementType::i64);
shapeOfOp1->set_friendly_name("shapeof1");
std::vector<int> reduce_axes = {0};
auto reduceAxesNode1 = std::dynamic_pointer_cast<ngraph::Node>(
std::make_shared<ngraph::opset3::Constant>(ngraph::element::Type_t::i64, ngraph::Shape({1}), reduce_axes));
auto reduceOp1 = ngraph::builder::makeReduce(shapeOfOp1, reduceAxesNode1, true, ngraph::helpers::ReductionType::Prod);
reduceOp1->set_friendly_name("reduce1");
std::vector<int64_t> shapePatternFill = {-1};
auto reshapePatternComp1 = std::make_shared<ngraph::opset3::Constant>(ngraph::element::Type_t::i64,
ngraph::Shape{1}, shapePatternFill);
auto concatOp1 = ngraph::builder::makeConcat({reduceOp1, reshapePatternComp1}, 0);
concatOp1->set_friendly_name("concat1");
auto reshapeOp1 = std::make_shared<ngraph::opset1::Reshape>(addOp1, concatOp1, false);
reshapeOp1->set_friendly_name("reshapeOp1");
auto addOp2 = ngraph::builder::makeEltwise(paramOuts[1], paramOuts[1], ngraph::helpers::EltwiseTypes::ADD);
addOp2->set_friendly_name("add2");
auto shapeOfOp2 = std::make_shared<ngraph::opset3::ShapeOf>(addOp2, ElementType::i64);
shapeOfOp2->set_friendly_name("shapeof2");
auto reduceAxesNode2 = std::dynamic_pointer_cast<ngraph::Node>(
std::make_shared<ngraph::opset3::Constant>(ngraph::element::Type_t::i64, ngraph::Shape({1}), reduce_axes));
auto reduceOp2 = ngraph::builder::makeReduce(shapeOfOp2, reduceAxesNode2, true, ngraph::helpers::ReductionType::Prod);
reduceOp2->set_friendly_name("reduce2");
auto reshapePatternComp2 = std::make_shared<ngraph::opset3::Constant>(ngraph::element::Type_t::i64,
ngraph::Shape{1}, shapePatternFill);
auto concatOp2 = ngraph::builder::makeConcat({reduceOp2, reshapePatternComp2}, 0);
concatOp2->set_friendly_name("concat2");
auto reshapeOp2 = std::make_shared<ngraph::opset1::Reshape>(addOp2, concatOp2, false);
reshapeOp2->set_friendly_name("reshapeOp2");
auto addOp3 = ngraph::builder::makeEltwise(reshapeOp1, reshapeOp2, ngraph::helpers::EltwiseTypes::ADD);
addOp3->set_friendly_name("add3");
auto shapeOf3 = std::make_shared<ngraph::opset3::ShapeOf>(addOp3, ElementType::i64);
shapeOf3->set_friendly_name("shapeof3");
ngraph::ResultVector results = {std::make_shared<ngraph::opset1::Result>(shapeOf3)};
function = std::make_shared<ngraph::Function>(results, params, "shapeof_out");
}
};
TEST_P(GenlImplKeyDynamicGPUTest, CompareWithRefs) {
SKIP_IF_CURRENT_TEST_IS_DISABLED()
run();
}
namespace {
std::map<std::string, std::string> emptyAdditionalConfig;
const std::vector<std::vector<ov::test::InputShape>> dynInputShapes = {
// 1D
{
// Input for ShapeOf
{{ov::Dimension::dynamic()}, {{30}, {40}, {50}}},
// Input for Add
{{ov::Dimension::dynamic(), ov::Dimension::dynamic()}, {{3, 10}, {2, 20}, {25, 2}}}
},
// 2D
{
// Input for ShapeOf
{{ov::Dimension::dynamic(), ov::Dimension::dynamic()}, {{1, 10}, {2, 20}}},
// Input for Add
{{ov::Dimension::dynamic(), ov::Dimension::dynamic(), ov::Dimension::dynamic()}, {{1, 1, 10}, {2, 10, 2}}}
},
// 3D
{
// Input for ShapeOf
{{ov::Dimension::dynamic(), ov::Dimension::dynamic(), ov::Dimension::dynamic()}, {{1, 10, 4}, {1, 4, 12}}},
// Input for Add
{{ov::Dimension::dynamic(), ov::Dimension::dynamic(), ov::Dimension::dynamic()}, {{1, 10, 4}, {2, 2, 12}}}
},
// 4D
{
// Input for ShapeOf
{{ov::Dimension::dynamic(), ov::Dimension::dynamic(), ov::Dimension::dynamic(), ov::Dimension::dynamic()}, {{3, 1, 10, 4}, {2, 4, 23, 12}}},
// Input for Add
{{ov::Dimension::dynamic(), ov::Dimension::dynamic()}, {{30, 4}, {24, 92}}}
}
};
const auto testParams_smoke = ::testing::Combine(::testing::ValuesIn(dynInputShapes),
::testing::ValuesIn(netPrecisions), // netprec
::testing::Values(CommonTestUtils::DEVICE_GPU),
::testing::Values(emptyAdditionalConfig));
INSTANTIATE_TEST_SUITE_P(smoke_dynamic_impl_key, GenlImplKeyDynamicGPUTest,
testParams_smoke, GenlImplKeyDynamicGPUTest::getTestCaseName);
} // namespace
} // namespace GPULayerTestsDefinitions