(
forward_fn: Callable[..., torch.Tensor],
chunk_size: int,
chunk_dim: int,
*input_tensors,
)
| 363 | |
| 364 | |
| 365 | def apply_chunking_to_forward( |
| 366 | forward_fn: Callable[..., torch.Tensor], |
| 367 | chunk_size: int, |
| 368 | chunk_dim: int, |
| 369 | *input_tensors, |
| 370 | ) -> torch.Tensor: |
| 371 | # Copied from transformers, the latest version of transformers deletes this function |
| 372 | assert len(input_tensors |
| 373 | ) > 0, f'{input_tensors} has to be a tuple/list of tensors' |
| 374 | |
| 375 | # inspect.signature exist since python 3.5 and is a python method -> no problem with backward compatibility |
| 376 | num_args_in_forward_chunk_fn = len( |
| 377 | inspect.signature(forward_fn).parameters) |
| 378 | if num_args_in_forward_chunk_fn != len(input_tensors): |
| 379 | raise ValueError( |
| 380 | f'forward_chunk_fn expects {num_args_in_forward_chunk_fn} arguments, but only {len(input_tensors)} input ' |
| 381 | 'tensors are given') |
| 382 | |
| 383 | if chunk_size > 0: |
| 384 | tensor_shape = input_tensors[0].shape[chunk_dim] |
| 385 | for input_tensor in input_tensors: |
| 386 | if input_tensor.shape[chunk_dim] != tensor_shape: |
| 387 | raise ValueError( |
| 388 | f'All input tenors have to be of the same shape: {tensor_shape}, ' |
| 389 | f'found shape {input_tensor.shape[chunk_dim]}') |
| 390 | |
| 391 | if input_tensors[0].shape[chunk_dim] % chunk_size != 0: |
| 392 | raise ValueError( |
| 393 | f'The dimension to be chunked {input_tensors[0].shape[chunk_dim]} has to be a multiple of the chunk ' |
| 394 | f'size {chunk_size}') |
| 395 | |
| 396 | num_chunks = input_tensors[0].shape[chunk_dim] // chunk_size |
| 397 | |
| 398 | # chunk input tensor into tuples |
| 399 | input_tensors_chunks = tuple( |
| 400 | input_tensor.chunk(num_chunks, dim=chunk_dim) |
| 401 | for input_tensor in input_tensors) |
| 402 | # apply forward fn to every tuple |
| 403 | output_chunks = tuple( |
| 404 | forward_fn(*input_tensors_chunk) |
| 405 | for input_tensors_chunk in zip(*input_tensors_chunks)) |
| 406 | # concatenate output at same dimension |
| 407 | return torch.cat(output_chunks, dim=chunk_dim) |
| 408 | |
| 409 | return forward_fn(*input_tensors) |
| 410 | |
| 411 | |
| 412 | def find_pruneable_heads_and_indices( |
no test coverage detected
searching dependent graphs…