MCPcopy Create free account
hub / github.com/TencentARC/BrushNet / set_attention_slice

Method set_attention_slice

src/diffusers/models/brushnet.py:609–672  ·  view source on GitHub ↗

r""" Enable sliced attention computation. When this option is enabled, the attention module splits the input tensor in slices to compute attention in several steps. This is useful for saving some memory in exchange for a small decrease in speed. Args: sl

(self, slice_size: Union[str, int, List[int]])

Source from the content-addressed store, hash-verified

607
608 # Copied from diffusers.models.unets.unet_2d_condition.UNet2DConditionModel.set_attention_slice
609 def set_attention_slice(self, slice_size: Union[str, int, List[int]]) -> None:
610 r"""
611 Enable sliced attention computation.
612
613 When this option is enabled, the attention module splits the input tensor in slices to compute attention in
614 several steps. This is useful for saving some memory in exchange for a small decrease in speed.
615
616 Args:
617 slice_size (`str` or `int` or `list(int)`, *optional*, defaults to `"auto"`):
618 When `"auto"`, input to the attention heads is halved, so attention is computed in two steps. If
619 `"max"`, maximum amount of memory is saved by running only one slice at a time. If a number is
620 provided, uses as many slices as `attention_head_dim // slice_size`. In this case, `attention_head_dim`
621 must be a multiple of `slice_size`.
622 """
623 sliceable_head_dims = []
624
625 def fn_recursive_retrieve_sliceable_dims(module: torch.nn.Module):
626 if hasattr(module, "set_attention_slice"):
627 sliceable_head_dims.append(module.sliceable_head_dim)
628
629 for child in module.children():
630 fn_recursive_retrieve_sliceable_dims(child)
631
632 # retrieve number of attention layers
633 for module in self.children():
634 fn_recursive_retrieve_sliceable_dims(module)
635
636 num_sliceable_layers = len(sliceable_head_dims)
637
638 if slice_size == "auto":
639 # half the attention head size is usually a good trade-off between
640 # speed and memory
641 slice_size = [dim // 2 for dim in sliceable_head_dims]
642 elif slice_size == "max":
643 # make smallest slice possible
644 slice_size = num_sliceable_layers * [1]
645
646 slice_size = num_sliceable_layers * [slice_size] if not isinstance(slice_size, list) else slice_size
647
648 if len(slice_size) != len(sliceable_head_dims):
649 raise ValueError(
650 f"You have provided {len(slice_size)}, but {self.config} has {len(sliceable_head_dims)} different"
651 f" attention layers. Make sure to match `len(slice_size)` to be {len(sliceable_head_dims)}."
652 )
653
654 for i in range(len(slice_size)):
655 size = slice_size[i]
656 dim = sliceable_head_dims[i]
657 if size is not None and size > dim:
658 raise ValueError(f"size {size} has to be smaller or equal to {dim}.")
659
660 # Recursively walk through all the children.
661 # Any children which exposes the set_attention_slice method
662 # gets the message
663 def fn_recursive_set_attention_slice(module: torch.nn.Module, slice_size: List[int]):
664 if hasattr(module, "set_attention_slice"):
665 module.set_attention_slice(slice_size.pop())
666

Calls

no outgoing calls