MCPcopy Create free account
hub / github.com/SooLab/CGFormer / apply_chunking_to_forward

Function apply_chunking_to_forward

bert/modeling_utils.py:1208–1268  ·  view source on GitHub ↗

This function chunks the `input_tensors` into smaller input tensor parts of size `chunk_size` over the dimension `chunk_dim`. It then applies a layer `forward_fn` to each chunk independently to save memory. If the `forward_fn` is independent across the `chunk_dim` this function will yie

(
    chunk_size: int, chunk_dim: int, forward_fn: Callable[..., torch.Tensor], *input_tensors
)

Source from the content-addressed store, hash-verified

1206
1207
1208def apply_chunking_to_forward(
1209 chunk_size: int, chunk_dim: int, forward_fn: Callable[..., torch.Tensor], *input_tensors
1210) -> torch.Tensor:
1211 """
1212 This function chunks the `input_tensors` into smaller input tensor parts of size `chunk_size` over the dimension `chunk_dim`.
1213 It then applies a layer `forward_fn` to each chunk independently to save memory.
1214 If the `forward_fn` is independent across the `chunk_dim` this function will yield the
1215 same result as not applying it.
1216
1217 Args:
1218 chunk_size: int - the chunk size of a chunked tensor. `num_chunks` = `len(input_tensors[0]) / chunk_size`
1219 chunk_dim: int - the dimension over which the input_tensors should be chunked
1220 forward_fn: fn - the forward fn of the model
1221 input_tensors: tuple(torch.Tensor) - the input tensors of `forward_fn` which are chunked
1222 Returns:
1223 a Tensor with the same shape the foward_fn would have given if applied
1224
1225
1226 Examples::
1227
1228 # rename the usual forward() fn to forward_chunk()
1229 def forward_chunk(self, hidden_states):
1230 hidden_states = self.decoder(hidden_states)
1231 return hidden_states
1232
1233 # implement a chunked forward function
1234 def forward(self, hidden_states):
1235 return apply_chunking_to_forward(self.chunk_size_lm_head, self.seq_len_dim, self.forward_chunk, hidden_states)
1236 """
1237
1238 assert len(input_tensors) > 0, "{} has to be a tuple/list of tensors".format(input_tensors)
1239 tensor_shape = input_tensors[0].shape
1240 assert all(
1241 input_tensor.shape == tensor_shape for input_tensor in input_tensors
1242 ), "All input tenors have to be of the same shape"
1243
1244 # inspect.signature exist since python 3.5 and is a python method -> no problem with backward compability
1245 num_args_in_forward_chunk_fn = len(inspect.signature(forward_fn).parameters)
1246 assert num_args_in_forward_chunk_fn == len(
1247 input_tensors
1248 ), "forward_chunk_fn expects {} arguments, but only {} input tensors are given".format(
1249 num_args_in_forward_chunk_fn, len(input_tensors)
1250 )
1251
1252 if chunk_size > 0:
1253 assert (
1254 input_tensors[0].shape[chunk_dim] % chunk_size == 0
1255 ), "The dimension to be chunked {} has to be a multiple of the chunk size {}".format(
1256 input_tensors[0].shape[chunk_dim], chunk_size
1257 )
1258
1259 num_chunks = input_tensors[0].shape[chunk_dim] // chunk_size
1260
1261 # chunk input tensor into tuples
1262 input_tensors_chunks = tuple(input_tensor.chunk(num_chunks, dim=chunk_dim) for input_tensor in input_tensors)
1263 # apply forward fn to every tuple
1264 output_chunks = tuple(forward_fn(*input_tensors_chunk) for input_tensors_chunk in zip(*input_tensors_chunks))
1265 # concatenate output at same dimension

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected