99
1010namespace ov ::op::internal {
1111
12+ template <typename TDim>
13+ bool merge_paged_selective_ssm_dim (TDim& destination, bool & initialized, const TDim& source) {
14+ if (!initialized) {
15+ destination = source;
16+ initialized = true ;
17+ return true ;
18+ }
19+ return TDim::merge (destination, destination, source);
20+ }
21+
1222template <class T , class TRShape = result_shape_t <T>>
1323std::vector<TRShape> shape_infer (const PagedSelectiveSSM* op, const std::vector<T>& input_shapes) {
1424 NODE_VALIDATION_CHECK (op, input_shapes.size () == 11 );
@@ -19,136 +29,132 @@ std::vector<TRShape> shape_infer(const PagedSelectiveSSM* op, const std::vector<
1929 NODE_SHAPE_INFER_CHECK (op, input_shapes, input_shapes[3 ].rank ().compatible (3 ));
2030 NODE_SHAPE_INFER_CHECK (op, input_shapes, input_shapes[4 ].rank ().compatible (3 ));
2131 NODE_SHAPE_INFER_CHECK (op, input_shapes, input_shapes[5 ].rank ().compatible (4 ));
22- for (size_t i = 6 ; i < 11 ; ++i ) {
23- NODE_SHAPE_INFER_CHECK (op, input_shapes, input_shapes[i ].rank ().compatible (1 ));
32+ for (size_t input = 6 ; input < 11 ; ++input ) {
33+ NODE_SHAPE_INFER_CHECK (op, input_shapes, input_shapes[input ].rank ().compatible (1 ));
2434 }
2535
26- const auto & A_ps = input_shapes[0 ];
27- const auto & dt_ps = input_shapes[1 ];
28- const auto & B_ps = input_shapes[2 ];
29- const auto & x_ps = input_shapes[3 ];
30- const auto & C_ps = input_shapes[4 ];
31- const auto & state_ps = input_shapes[5 ];
32- const auto & subsequence_begins_ps = input_shapes[6 ];
33- const auto & la_block_indices_ps = input_shapes[7 ];
34- const auto & la_block_indices_begins_ps = input_shapes[8 ];
35- const auto & num_processed_tokens_ps = input_shapes[9 ];
36- const auto & cache_interval_ps = input_shapes[10 ];
37-
38- const auto A_rank_is_static = A_ps.rank ().is_static ();
39- const auto dt_rank_is_static = dt_ps.rank ().is_static ();
40- const auto B_rank_is_static = B_ps.rank ().is_static ();
41- const auto x_rank_is_static = x_ps.rank ().is_static ();
42- const auto C_rank_is_static = C_ps.rank ().is_static ();
43- const auto state_rank_is_static = state_ps.rank ().is_static ();
44- const auto subsequence_begins_rank_is_static = subsequence_begins_ps.rank ().is_static ();
45- const auto la_block_indices_rank_is_static = la_block_indices_ps.rank ().is_static ();
46- const auto la_block_indices_begins_rank_is_static = la_block_indices_begins_ps.rank ().is_static ();
47- const auto num_processed_tokens_rank_is_static = num_processed_tokens_ps.rank ().is_static ();
48- const auto cache_interval_rank_is_static = cache_interval_ps.rank ().is_static ();
49-
50- Dimension token_dim, num_heads_dim, head_dim_dim, state_size_dim;
51-
36+ const auto & A_shape = input_shapes[0 ];
37+ const auto & dt_shape = input_shapes[1 ];
38+ const auto & B_shape = input_shapes[2 ];
39+ const auto & x_shape = input_shapes[3 ];
40+ const auto & C_shape = input_shapes[4 ];
41+ const auto & state_shape = input_shapes[5 ];
42+ const auto & subsequence_shape = input_shapes[6 ];
43+ const auto & block_indices_begins_shape = input_shapes[8 ];
44+ const auto & processed_shape = input_shapes[9 ];
45+ const auto & interval_shape = input_shapes[10 ];
46+ using DimType = typename T::value_type;
47+
48+ DimType token_dim{};
49+ DimType heads_dim{};
50+ DimType head_dim{};
51+ DimType groups_dim{};
52+ DimType state_size_dim{};
53+
54+ bool token_initialized = false ;
5255 bool token_ok = true ;
53- if (x_rank_is_static )
54- token_ok &= Dimension::merge (token_dim, token_dim, x_ps [0 ]);
55- if (dt_rank_is_static )
56- token_ok &= Dimension::merge (token_dim, token_dim, dt_ps [0 ]);
57- if (B_rank_is_static )
58- token_ok &= Dimension::merge (token_dim, token_dim, B_ps [0 ]);
59- if (C_rank_is_static )
60- token_ok &= Dimension::merge (token_dim, token_dim, C_ps [0 ]);
56+ if (x_shape. rank (). is_static () )
57+ token_ok &= merge_paged_selective_ssm_dim (token_dim, token_initialized, x_shape [0 ]);
58+ if (dt_shape. rank (). is_static () )
59+ token_ok &= merge_paged_selective_ssm_dim (token_dim, token_initialized, dt_shape [0 ]);
60+ if (B_shape. rank (). is_static () )
61+ token_ok &= merge_paged_selective_ssm_dim (token_dim, token_initialized, B_shape [0 ]);
62+ if (C_shape. rank (). is_static () )
63+ token_ok &= merge_paged_selective_ssm_dim (token_dim, token_initialized, C_shape [0 ]);
6164 NODE_SHAPE_INFER_CHECK (op,
6265 input_shapes,
6366 token_ok,
6467 " The token dimension of `dt`, `B`, `x` and `C` should be the same." );
6568
66- bool num_heads_ok = true ;
67- if (x_rank_is_static)
68- num_heads_ok &= Dimension::merge (num_heads_dim, num_heads_dim, x_ps[1 ]);
69- if (A_rank_is_static)
70- num_heads_ok &= Dimension::merge (num_heads_dim, num_heads_dim, A_ps[0 ]);
71- if (dt_rank_is_static)
72- num_heads_ok &= Dimension::merge (num_heads_dim, num_heads_dim, dt_ps[1 ]);
73- if (state_rank_is_static)
74- num_heads_ok &= Dimension::merge (num_heads_dim, num_heads_dim, state_ps[1 ]);
69+ bool heads_initialized = false ;
70+ bool heads_ok = true ;
71+ if (x_shape.rank ().is_static ())
72+ heads_ok &= merge_paged_selective_ssm_dim (heads_dim, heads_initialized, x_shape[1 ]);
73+ if (A_shape.rank ().is_static ())
74+ heads_ok &= merge_paged_selective_ssm_dim (heads_dim, heads_initialized, A_shape[0 ]);
75+ if (dt_shape.rank ().is_static ())
76+ heads_ok &= merge_paged_selective_ssm_dim (heads_dim, heads_initialized, dt_shape[1 ]);
77+ if (state_shape.rank ().is_static ())
78+ heads_ok &= merge_paged_selective_ssm_dim (heads_dim, heads_initialized, state_shape[1 ]);
7579 NODE_SHAPE_INFER_CHECK (op,
7680 input_shapes,
77- num_heads_ok ,
81+ heads_ok ,
7882 " The number of heads of `A`, `dt`, `x` and `recurrent_state_table` should be the same." );
7983
80- if (B_rank_is_static && C_rank_is_static) {
81- NODE_SHAPE_INFER_CHECK (op,
82- input_shapes,
83- C_ps[1 ].compatible (B_ps[1 ]),
84- " The number of groups of `B` and `C` should be the same." );
85- }
86-
84+ bool head_dim_initialized = false ;
8785 bool head_dim_ok = true ;
88- if (x_rank_is_static )
89- head_dim_ok &= Dimension::merge (head_dim_dim, head_dim_dim, x_ps [2 ]);
90- if (state_rank_is_static )
91- head_dim_ok &= Dimension::merge (head_dim_dim, head_dim_dim, state_ps [2 ]);
86+ if (x_shape. rank (). is_static () )
87+ head_dim_ok &= merge_paged_selective_ssm_dim (head_dim, head_dim_initialized, x_shape [2 ]);
88+ if (state_shape. rank (). is_static () )
89+ head_dim_ok &= merge_paged_selective_ssm_dim (head_dim, head_dim_initialized, state_shape [2 ]);
9290 NODE_SHAPE_INFER_CHECK (op,
9391 input_shapes,
9492 head_dim_ok,
9593 " The head dimension of `x` and `recurrent_state_table` should be the same." );
9694
95+ bool groups_initialized = false ;
96+ bool groups_ok = true ;
97+ if (B_shape.rank ().is_static ())
98+ groups_ok &= merge_paged_selective_ssm_dim (groups_dim, groups_initialized, B_shape[1 ]);
99+ if (C_shape.rank ().is_static ())
100+ groups_ok &= merge_paged_selective_ssm_dim (groups_dim, groups_initialized, C_shape[1 ]);
101+ NODE_SHAPE_INFER_CHECK (op, input_shapes, groups_ok, " The number of groups of `B` and `C` should be the same." );
102+ NODE_SHAPE_INFER_CHECK (op,
103+ input_shapes,
104+ groups_dim.is_dynamic () || groups_dim.get_length () > 0 ,
105+ " The number of groups must be greater than zero." );
106+
107+ bool state_size_initialized = false ;
97108 bool state_size_ok = true ;
98- if (state_rank_is_static )
99- state_size_ok &= Dimension::merge (state_size_dim, state_size_dim, state_ps [3 ]);
100- if (B_rank_is_static )
101- state_size_ok &= Dimension::merge (state_size_dim, state_size_dim, B_ps [2 ]);
102- if (C_rank_is_static )
103- state_size_ok &= Dimension::merge (state_size_dim, state_size_dim, C_ps [2 ]);
109+ if (state_shape. rank (). is_static () )
110+ state_size_ok &= merge_paged_selective_ssm_dim (state_size_dim, state_size_initialized, state_shape [3 ]);
111+ if (B_shape. rank (). is_static () )
112+ state_size_ok &= merge_paged_selective_ssm_dim (state_size_dim, state_size_initialized, B_shape [2 ]);
113+ if (C_shape. rank (). is_static () )
114+ state_size_ok &= merge_paged_selective_ssm_dim (state_size_dim, state_size_initialized, C_shape [2 ]);
104115 NODE_SHAPE_INFER_CHECK (op,
105116 input_shapes,
106117 state_size_ok,
107118 " The state size of `B`, `C` and `recurrent_state_table` should be the same." );
119+ NODE_SHAPE_INFER_CHECK (op,
120+ input_shapes,
121+ state_size_dim.is_dynamic () || state_size_dim.get_length () > 0 ,
122+ " The state size must be greater than zero." );
108123
109- if (num_heads_dim.is_static () && B_rank_is_static) {
110- const auto & num_groups = B_ps[1 ];
111- if (num_groups.is_static ()) {
112- NODE_SHAPE_INFER_CHECK (
113- op,
114- input_shapes,
115- num_groups.get_length () != 0 && num_heads_dim.get_length () % num_groups.get_length () == 0 ,
116- " The number of heads should be divisible by the number of groups." );
117- }
124+ if (heads_dim.is_static () && groups_dim.is_static ()) {
125+ NODE_SHAPE_INFER_CHECK (op,
126+ input_shapes,
127+ groups_dim.get_length () != 0 && heads_dim.get_length () % groups_dim.get_length () == 0 ,
128+ " The number of heads should be divisible by the number of groups." );
118129 }
119130
120- if (la_block_indices_rank_is_static && state_rank_is_static ) {
131+ if (subsequence_shape. rank (). is_static () && block_indices_begins_shape. rank (). is_static () ) {
121132 NODE_SHAPE_INFER_CHECK (op,
122133 input_shapes,
123- la_block_indices_ps[0 ].compatible (state_ps[0 ]),
124- " The number of blocks of `la_block_indices` and `recurrent_state_table` should "
125- " be the same." );
134+ subsequence_shape[0 ].compatible (block_indices_begins_shape[0 ]),
135+ " The sizes of `subsequence_begins` and `la_block_indices_begins` should be the same." );
126136 }
127- if (subsequence_begins_rank_is_static && la_block_indices_begins_rank_is_static ) {
137+ if (processed_shape. rank (). is_static () && interval_shape. rank (). is_static () ) {
128138 NODE_SHAPE_INFER_CHECK (op,
129139 input_shapes,
130- subsequence_begins_ps[0 ].compatible (la_block_indices_begins_ps[0 ]),
131- " The number of sequences of `subsequence_begins` and `la_block_indices_begins` "
132- " should be the same." );
140+ processed_shape[0 ].compatible (interval_shape[0 ]),
141+ " The sizes of `num_processed_tokens` and `cache_interval` should be the same." );
133142 }
134- if (num_processed_tokens_rank_is_static && cache_interval_rank_is_static ) {
143+ if (subsequence_shape. rank (). is_static () && processed_shape. rank (). is_static () ) {
135144 NODE_SHAPE_INFER_CHECK (op,
136145 input_shapes,
137- num_processed_tokens_ps[0 ].compatible (cache_interval_ps[0 ]),
138- " The number of sequences of `num_processed_tokens` and `cache_interval` should "
139- " be the same." );
140- }
141- if (subsequence_begins_rank_is_static && num_processed_tokens_rank_is_static) {
146+ subsequence_shape[0 ].is_dynamic () || subsequence_shape[0 ].get_length () >= 1 ,
147+ " The size of `subsequence_begins` must be at least one." );
142148 NODE_SHAPE_INFER_CHECK (op,
143149 input_shapes,
144- (subsequence_begins_ps [0 ] - Dimension (1 )).compatible (num_processed_tokens_ps [0 ]),
145- " The number of sequences of `subsequence_begins` and `num_processed_tokens` "
146- " should be the same ." );
150+ (subsequence_shape [0 ] - DimType (1 )).compatible (processed_shape [0 ]),
151+ " The size of `subsequence_begins` should be one larger than "
152+ " `num_processed_tokens` ." );
147153 }
148154
149- auto output_shapes = std::vector<TRShape>{x_ps };
150- if (x_rank_is_static ) {
151- output_shapes[0 ] = TRShape{token_dim, num_heads_dim, head_dim_dim };
155+ auto output_shapes = std::vector<TRShape>{x_shape };
156+ if (x_shape. rank (). is_static () ) {
157+ output_shapes[0 ] = TRShape{token_dim, heads_dim, head_dim };
152158 }
153159 return output_shapes;
154160}
0 commit comments