Instructions to use Cccccz/HY with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Diffusers
How to use Cccccz/HY with Diffusers:
pip install -U diffusers transformers accelerate
import torch from diffusers import DiffusionPipeline # switch to "mps" for apple devices pipe = DiffusionPipeline.from_pretrained("Cccccz/HY", dtype=torch.bfloat16, device_map="cuda") prompt = "Astronaut in a jungle, cold color palette, muted colors, detailed, 8k" image = pipe(prompt).images[0] - Notebooks
- Google Colab
- Kaggle
Download wan/models/par_vae/context_parallel/plugins.py from Cccccz/HY: direct link, hf CLI and curl.
- Browser
- Download file 16 kB
-
https://huggingface.co/Cccccz/HY/resolve/main/wan/models/par_vae/context_parallel/plugins.py
- Command line
-
hf download hf://Cccccz/HY/wan/models/par_vae/context_parallel/plugins.py
-
curl -L -o plugins.py https://huggingface.co/Cccccz/HY/resolve/main/wan/models/par_vae/context_parallel/plugins.py
16 kB
| import torch | |
| import torch.distributed as dist | |
| import math | |
| import time | |
| class ModulePlugin: | |
| def __init__(self, module, module_id, global_state=None): | |
| self.module = module | |
| self.module_id = module_id | |
| self.global_state = global_state | |
| self.enable = True | |
| self.implement_forward() | |
| def is_log_node(self): | |
| return ( | |
| self.global_state.get("dist_controller").rank == 0 | |
| and self.module_id[1] == 0 | |
| ) | |
| def t(self): | |
| return self.global_state.get("timestep") | |
| def p(self): | |
| return self.t / 1000 | |
| def implement_forward(self): | |
| module = self.module | |
| if not hasattr(module, "old_forward"): | |
| module.old_forward = module.forward | |
| self.new_forward = self.get_new_forward() | |
| def forward(*args, **kwargs): | |
| self.update_config() # update config | |
| return ( | |
| self.new_forward(*args, **kwargs) | |
| if self.enable | |
| else self.old_forward(*args, **kwargs) | |
| ) | |
| module.forward = forward | |
| def set_enable(self, enable=True): | |
| self.enable = enable | |
| def get_new_forward(self): | |
| raise NotImplementedError | |
| def update_config(self, config: dict = None): | |
| if config is None: | |
| config = self.global_state.get("plugin_configs", {}).get( | |
| self.module_id[0], {} | |
| ) | |
| for key, value in config.items(): | |
| setattr(self, key, value) | |
| def _calculate_padding(self, kernel_size, chunk_dim): | |
| """Calculate padding parameters for convolution layers. | |
| Args: | |
| kernel_size: kernel size tuple or int | |
| chunk_dim: dimension to chunk/pad along | |
| Returns: | |
| tuple: (padding_left, padding_right, padding_flag) | |
| """ | |
| if isinstance(kernel_size, int): | |
| kernel_size = tuple([kernel_size] * (chunk_dim - 1)) | |
| # For 3D conv, use width dimension (index 2) | |
| # For 2D conv, calculate based on chunk_dim | |
| if len(kernel_size) == 3: | |
| kernel_width = kernel_size[2] | |
| else: | |
| pad_kernel_dim = chunk_dim - 3 | |
| kernel_width = kernel_size[pad_kernel_dim] | |
| d = kernel_width - 1 | |
| padding_left = d // 2 | |
| padding_right = d - padding_left | |
| padding_flag = padding_left if d > 0 else 0 | |
| return padding_left, padding_right, padding_flag | |
| def _pad_context_bilateral_impl( | |
| self, h, padding_left, padding_right, slice_dim, cat_dim | |
| ): | |
| """Core implementation for bilateral padding with context from adjacent ranks. | |
| Args: | |
| h: input tensor to pad | |
| padding_left: number of elements to pad on left | |
| padding_right: number of elements to pad on right | |
| slice_dim: dimension to slice from (3 for 3D, 3 for 2D height/width) | |
| cat_dim: dimension to concatenate along | |
| Returns: | |
| padded tensor with context from adjacent ranks | |
| """ | |
| if padding_left == 0: | |
| return h | |
| # Extract slices to share with neighbors | |
| if slice_dim == 3: | |
| share_to_left = h[:, :, :, :padding_left].contiguous() | |
| share_to_right = h[:, :, :, -padding_right:].contiguous() | |
| elif slice_dim == 4: | |
| share_to_left = h[:, :, :, :, :padding_left].contiguous() | |
| share_to_right = h[:, :, :, :, -padding_right:].contiguous() | |
| elif slice_dim == 2: | |
| share_to_left = h[:, :, :padding_left].contiguous() | |
| share_to_right = h[:, :, -padding_right:].contiguous() | |
| else: # slice_dim == 1 | |
| share_to_left = h[:, :, :, :padding_left].contiguous() | |
| share_to_right = h[:, :, :, -padding_right:].contiguous() | |
| rank = dist.get_rank() | |
| world_size = dist.get_world_size() | |
| adj_groups = self.global_state.get("dist_controller").adj_groups | |
| if rank % 2: | |
| # Odd rank: pad left first, then right | |
| if rank: | |
| padding_list = [torch.zeros_like(share_to_left) for _ in range(2)] | |
| dist.all_gather(padding_list, share_to_left, group=adj_groups[rank - 1]) | |
| left_context = padding_list[0].to(h.device, non_blocking=True) | |
| else: | |
| left_context = torch.zeros_like(share_to_left).to( | |
| h.device, non_blocking=True | |
| ) | |
| if rank != world_size - 1: | |
| padding_list = [torch.zeros_like(share_to_right) for _ in range(2)] | |
| dist.all_gather(padding_list, share_to_right, group=adj_groups[rank]) | |
| right_context = padding_list[1].to(h.device, non_blocking=True) | |
| else: | |
| right_context = torch.zeros_like(share_to_right).to( | |
| h.device, non_blocking=True | |
| ) | |
| else: | |
| # Even rank: pad right first, then left | |
| if rank != world_size - 1: | |
| padding_list = [torch.zeros_like(share_to_right) for _ in range(2)] | |
| dist.all_gather(padding_list, share_to_right, group=adj_groups[rank]) | |
| right_context = padding_list[1].to(h.device, non_blocking=True) | |
| else: | |
| right_context = torch.zeros_like(share_to_right).to( | |
| h.device, non_blocking=True | |
| ) | |
| if rank: | |
| padding_list = [torch.zeros_like(share_to_left) for _ in range(2)] | |
| dist.all_gather(padding_list, share_to_left, group=adj_groups[rank - 1]) | |
| left_context = padding_list[0].to(h.device, non_blocking=True) | |
| else: | |
| left_context = torch.zeros_like(share_to_left).to( | |
| h.device, non_blocking=True | |
| ) | |
| h_with_context = torch.cat([left_context, h, right_context], dim=cat_dim) | |
| return h_with_context | |
| def _pad_context_bilateral(self, h, padding_left, padding_right, chunk_dim): | |
| """Pad tensor with context from adjacent ranks using bilateral communication. | |
| Args: | |
| h: input tensor to pad | |
| padding_left: number of elements to pad on left | |
| padding_right: number of elements to pad on right | |
| chunk_dim: dimension to pad along | |
| Returns: | |
| padded tensor with context from adjacent ranks | |
| """ | |
| slice_dim = 3 if chunk_dim == 3 else 4 | |
| return self._pad_context_bilateral_impl( | |
| h, padding_left, padding_right, slice_dim, chunk_dim | |
| ) | |
| def _pad_context_bilateral_2d(self, h, padding_left, padding_right, chunk_dim): | |
| """Pad 2D tensor with context from adjacent ranks using bilateral communication. | |
| Similar to _pad_context_bilateral but pads on chunk_dim-1 dimension for 2D convolutions. | |
| Args: | |
| h: input tensor to pad | |
| padding_left: number of elements to pad on left | |
| padding_right: number of elements to pad on right | |
| chunk_dim: base dimension reference (actual padding on chunk_dim-1) | |
| Returns: | |
| padded tensor with context from adjacent ranks | |
| """ | |
| slice_dim = 2 if chunk_dim == 3 else 1 | |
| return self._pad_context_bilateral_impl( | |
| h, padding_left, padding_right, slice_dim, chunk_dim - 1 | |
| ) | |
| class GroupNormPlugin(ModulePlugin): | |
| def __init__(self, module, module_id, global_state=None): | |
| super().__init__(module, module_id, global_state) | |
| def get_new_forward(self): | |
| module = self.module | |
| def new_forward(x): | |
| shape = x.shape | |
| N, C, G = shape[0], shape[1], module.num_groups | |
| assert C % G == 0 | |
| x = x.reshape(N, G, -1) | |
| mean = x.mean(-1, keepdim=True).to(torch.float32) | |
| dist.all_reduce(mean) | |
| mean = mean / dist.get_world_size() | |
| var = ((x - mean.to(x.dtype)) ** 2).mean(-1, keepdim=True).to(torch.float32) | |
| dist.all_reduce(var) | |
| var = var / dist.get_world_size() | |
| x = (x - mean.to(x.dtype)) / (var.to(x.dtype) + module.eps).sqrt() | |
| x = x.view(shape) | |
| new_shape = [1 for _ in shape] | |
| new_shape[1] = -1 | |
| return x * module.weight.view(new_shape) + module.bias.view(new_shape) | |
| return new_forward | |
| class Conv3DSafeNewPligin(ModulePlugin): | |
| def __init__(self, module, module_id, global_state=None): | |
| super().__init__(module, module_id, global_state) | |
| self.kernel_size = getattr(module, "kernel_size", (1, 1, 1)) | |
| if isinstance(self.kernel_size, int): | |
| self.kernel_size = (self.kernel_size, self.kernel_size, self.kernel_size) | |
| self.chunk_dim = global_state.get("chunk_dim") | |
| self.padding_left, self.padding_right, self.padding_flag = ( | |
| self._calculate_padding(self.kernel_size, self.chunk_dim) | |
| ) | |
| def pad_context(self, h): | |
| return self._pad_context_bilateral( | |
| h, self.padding_left, self.padding_right, self.chunk_dim | |
| ) | |
| def get_new_forward(self): | |
| module = self.module | |
| def new_forward(hidden_states, cache_x=None, *args, **kwargs): | |
| if self.padding_flag == 0: | |
| # print(f"padding=0, return old_forward") | |
| return module.old_forward(hidden_states, cache_x, *args, **kwargs) | |
| hidden_states = self.pad_context(hidden_states) | |
| if cache_x is not None: | |
| cache_x = self.pad_context(cache_x) | |
| result = module.old_forward(hidden_states, cache_x, *args, **kwargs) | |
| if self.chunk_dim == 3: | |
| result = result[ | |
| :, | |
| :, | |
| :, | |
| self.padding_left : ( | |
| -self.padding_right if self.padding_right > 0 else None | |
| ), | |
| ] | |
| else: | |
| result = result[ | |
| :, | |
| :, | |
| :, | |
| :, | |
| self.padding_left : ( | |
| -self.padding_right if self.padding_right > 0 else None | |
| ), | |
| ] | |
| return result | |
| return new_forward | |
| class Conv2DSafeNewPligin(ModulePlugin): | |
| def __init__(self, module, module_id, global_state=None): | |
| super().__init__(module, module_id, global_state) | |
| self.kernel_size = getattr(module, "kernel_size", (1, 1)) | |
| self.stride = getattr(module, "stride", (1, 1)) | |
| if isinstance(self.kernel_size, int): | |
| self.kernel_size = (self.kernel_size, self.kernel_size) | |
| self.chunk_dim = global_state.get("chunk_dim") | |
| pad_kernel_dim = self.chunk_dim - 3 | |
| kernel_height = self.kernel_size[pad_kernel_dim] | |
| d = kernel_height - 1 | |
| self.padding_left = d // 2 | |
| self.padding_right = d - self.padding_left | |
| self.padding = self.padding_left if d > 0 else 0 | |
| def pad_context(self, h): | |
| return self._pad_context_bilateral_2d( | |
| h, self.padding_left, self.padding_right, self.chunk_dim | |
| ) | |
| def get_new_forward(self): | |
| module = self.module | |
| def new_forward(hidden_states: torch.Tensor) -> torch.Tensor: | |
| if self.padding == 0: | |
| return module.old_forward(hidden_states) | |
| hidden_states = self.pad_context(hidden_states) | |
| if self.chunk_dim == 3: | |
| hidden_states = module.old_forward(hidden_states)[ | |
| :, | |
| :, | |
| self.padding_left : ( | |
| -self.padding_right if self.padding_right > 0 else None | |
| ), | |
| ] | |
| else: | |
| hidden_states = module.old_forward(hidden_states)[ | |
| :, | |
| :, | |
| :, | |
| self.padding_left : ( | |
| -self.padding_right if self.padding_right > 0 else None | |
| ), | |
| ] | |
| return hidden_states | |
| return new_forward | |
| class Conv2DSafeNewPliginStride2(ModulePlugin): | |
| def __init__(self, module, module_id, global_state=None): | |
| super().__init__(module, module_id, global_state) | |
| self.kernel_size = getattr(module, "kernel_size", (1, 1)) | |
| self.stride = getattr(module, "stride", (1, 1)) | |
| if isinstance(self.kernel_size, int): | |
| self.kernel_size = (self.kernel_size, self.kernel_size) | |
| self.chunk_dim = global_state.get("chunk_dim") | |
| assert self.kernel_size[0] == self.kernel_size[1] | |
| kernel_height = self.kernel_size[0] | |
| d = kernel_height - 1 | |
| self.padding_left = d // 2 | |
| self.padding_right = d - self.padding_left | |
| self.padding = self.padding_left if d > 0 else 0 | |
| def pad_context(self, h): | |
| if self.padding == 0: | |
| return h | |
| rank = dist.get_rank() | |
| world_size = dist.get_world_size() | |
| if self.chunk_dim == 3: | |
| share_to_left = h[:, :, : self.padding_left].contiguous() | |
| else: | |
| share_to_left = h[:, :, :, : self.padding_left].contiguous() | |
| if rank < world_size - 1: | |
| right_context = torch.zeros_like(share_to_left) | |
| dist.recv(right_context, src=rank + 1) | |
| if rank > 0: | |
| dist.send(share_to_left, dst=rank - 1) | |
| # torch.cuda.synchronize() | |
| if rank < world_size - 1: | |
| h_with_context = torch.cat([h, right_context], dim=self.chunk_dim - 1) | |
| else: | |
| h_with_context = h | |
| return h_with_context | |
| def get_new_forward(self): | |
| module = self.module | |
| def new_forward(hidden_states: torch.Tensor) -> torch.Tensor: | |
| # assert self.global_state["chunk_dim"] == 3 # only support chunk height now | |
| if self.padding == 0: | |
| return module.old_forward(hidden_states) | |
| if self.chunk_dim == 3: | |
| hidden_states = hidden_states[:, :, :-1, :] | |
| else: | |
| hidden_states = hidden_states[:, :, :, :-1] | |
| hidden_states = self.pad_context(hidden_states) | |
| if self.chunk_dim == 3: | |
| hidden_states = torch.nn.functional.pad(hidden_states, (0, 0, 0, 1)) | |
| else: | |
| hidden_states = torch.nn.functional.pad(hidden_states, (0, 1)) | |
| hidden_states = module.old_forward( | |
| hidden_states | |
| ) # [:,:,self.padding_left:-self.padding_right if self.padding_right > 0 else None] | |
| return hidden_states | |
| return new_forward | |
| class WanAttentionPlugin(ModulePlugin): | |
| def __init__(self, module, module_id, global_state=None): | |
| self.rank = dist.get_rank() | |
| self.world_size = dist.get_world_size() | |
| self.gather_dim = global_state.get("chunk_dim") | |
| super().__init__(module, module_id, global_state) | |
| def get_new_forward(self): | |
| module = self.module | |
| rank = self.rank | |
| world_size = self.world_size | |
| def new_forward(hidden_states: torch.Tensor) -> torch.Tensor: | |
| gathered_tensors = [ | |
| torch.zeros_like(hidden_states) for _ in range(world_size) | |
| ] | |
| dist.all_gather(gathered_tensors, hidden_states) | |
| combined_tensor = torch.cat(gathered_tensors, dim=self.gather_dim) | |
| forward_output = module.old_forward(combined_tensor) | |
| # chunk_sizes = [t.size(self.gather_dim) for t in gathered_tensors] | |
| # start_idx = sum(chunk_sizes[:rank]) | |
| # end_idx = start_idx + chunk_sizes[rank] | |
| # local_output = forward_output[:, :, :, start_idx:end_idx].contiguous() | |
| local_output = forward_output.chunk(chunks=world_size, dim=self.gather_dim)[ | |
| rank | |
| ] | |
| return local_output | |
| return new_forward | |