@@ -8542,8 +8542,10 @@ def __init__(self, new_dim, **kwargs):
85428542 :param DimensionTag new_dim:
85438543 """
85448544 super (CumConcatLayer , self ).__init__ (** kwargs )
8545- assert self .network .is_inside_rec_layer ()
8545+ rec_layer = self .network .get_rec_parent_layer (inside_loop = False )
8546+ assert rec_layer , "%r must be used inside a RecLayer" % self
85468547 out_axis = self .output .get_axis_from_description (new_dim )
8548+ new_dim_ = self .output .dim_tags [out_axis ]
85478549
85488550 if self .network .is_inside_rec_layer (inside_loop = True ):
85498551 current_data = self .input_data .copy_compatible_to (self .output , unbroadcast = False )
@@ -8553,21 +8555,31 @@ def __init__(self, new_dim, **kwargs):
85538555 self .rec_vars_outputs ["state" ] = concat_frames
85548556 self .output .placeholder = concat_frames
85558557
8556- dyn_size = tf .broadcast_to (self .network .get_rec_step_index () + 1 , [data .get_batch_dim ()])
8558+ if not new_dim_ .dyn_size_ext :
8559+ # Unbroadcasting to [B] is not needed because any layers operating on this
8560+ # should be able to handle extended dyn sizes.
8561+ # Clipping it to the max length for sequences in the loop which are already ended
8562+ # (i.e. considering the end flag)
8563+ # is also not needed because any calculations after the end are irrelevant.
8564+ dyn_size = self .network .get_rec_step_index () + 1 # scalar
8565+ new_dim_ .dyn_size_ext = Data (
8566+ name = "%s:cum-concat:size-inside" % self .name ,
8567+ dim_tags = [], # scalar
8568+ placeholder = dyn_size )
85578569
85588570 else :
8559- # If not inside a rec loop, this layer is a no-op
8560- self .output .placeholder = None # TODO
8561- data . size_placeholder = self . input_data . size_placeholder . copy ()
8562- dyn_size = tf . identity ( data . get_dynamic_size ( out_axis ))
8563-
8564- # We already set the size_placeholder to a dummy rec-history before, now do it properly
8565- from returnn . tf . util . basic import DimensionTag
8566- tag = DimensionTag (
8567- description = "rec-history:%s" % self . get_absolute_name (),
8568- kind = DimensionTag . Types . Time )
8569- data . size_placeholder [ data . get_batch_axis_excluding_batch ( out_axis )] = dyn_size
8570- tag . set_tag_on_size_tensor ( dyn_size )
8571+ # If not inside a rec loop, this layer is a no-op on the tensor.
8572+ self .output .placeholder = self . input_data . placeholder
8573+
8574+ # However, we used new dim tags, which were already prepared.
8575+ # We now must fill in the extended dynamic size information.
8576+ if not new_dim_ . dyn_size_ext :
8577+ # This must match the logic above for inside the loop.
8578+ dyn_size = tf . range ( tf . math . reduce_max ( rec_layer . time_dim_tag . dyn_size )) + 1 # [T]
8579+ new_dim_ . dyn_size_ext = Data (
8580+ name = "%s:cum-concat:size-outside" % self . name ,
8581+ dim_tags = [ rec_layer . time_dim_tag ],
8582+ placeholder = dyn_size )
85718583
85728584 @classmethod
85738585 def get_out_data_from_opts (cls , name , network , sources , new_dim , ** kwargs ):
0 commit comments