Skip to content

Commit 66967d0

Browse files
committed
Revert "[platform]: flux2 & tp"
This reverts commit e00a254.
1 parent 02c8fc9 commit 66967d0

4 files changed

Lines changed: 207 additions & 466 deletions

File tree

lightx2v/models/networks/flux2/infer/transformer_infer.py

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,6 @@ def __init__(self, config):
1313
self.infer_conditional = True
1414
self.clean_cuda_cache = self.config.get("clean_cuda_cache", False)
1515

16-
self.tp_group = None
17-
self.tp_rank = 0
18-
self.tp_size = 1
19-
if self.config.get("tensor_parallel", False):
20-
self.tp_group = self.config.get("device_mesh").get_group(mesh_dim="tensor_p")
21-
self.tp_rank = dist.get_rank(self.tp_group)
22-
self.tp_size = dist.get_world_size(self.tp_group)
23-
2416
self.inner_dim = config.get("num_attention_heads", 24) * config.get("attention_head_dim", 64)
2517

2618
if self.config.get("seq_parallel", False):
@@ -66,7 +58,7 @@ def infer_double_stream_block(
6658
image_rotary_emb,
6759
img_attn_hook=None,
6860
):
69-
heads = self.config["num_attention_heads"] // self.tp_size
61+
heads = self.config["num_attention_heads"]
7062
head_dim = self.config["attention_head_dim"]
7163

7264
(shift_msa, scale_msa, gate_msa), (shift_mlp, scale_mlp, gate_mlp) = self._split_double_modulation(temb_mod_img)
@@ -177,7 +169,7 @@ def infer_single_stream_block(
177169
image_rotary_emb,
178170
num_txt_tokens=0,
179171
):
180-
heads = self.config["num_attention_heads"] // self.tp_size
172+
heads = self.config["num_attention_heads"]
181173
head_dim = self.config["attention_head_dim"]
182174

183175
if encoder_hidden_states is not None:

lightx2v/models/networks/flux2/model.py

Lines changed: 0 additions & 239 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
from lightx2v.models.networks.flux2.weights.pre_weights import Flux2DevPreWeights, Flux2PreWeights
1313
from lightx2v.models.networks.flux2.weights.transformer_weights import Flux2TransformerWeights
1414
from lightx2v.utils.custom_compiler import compiled_method
15-
from lightx2v_platform.base import global_var
1615

1716

1817
class _Flux2TransformerModelBase(BaseTransformerModel):
@@ -25,248 +24,10 @@ def __init__(self, config, model_path, device):
2524
super().__init__(model_path, config, device)
2625
self.in_channels = self.config.get("transformer_in_channels", self.config.get("in_channels", 64))
2726
self.attention_kwargs = {}
28-
self._init_tensor_parallel()
2927
self._init_infer_class()
3028
self._init_weights()
3129
self._init_infer()
3230

33-
def _init_tensor_parallel(self):
34-
if self.config.get("tensor_parallel", False):
35-
self.use_tp = True
36-
self.tp_group = self.config.get("device_mesh").get_group(mesh_dim="tensor_p")
37-
self.tp_rank = dist.get_rank(self.tp_group)
38-
self.tp_size = dist.get_world_size(self.tp_group)
39-
else:
40-
self.use_tp = False
41-
self.tp_group = None
42-
self.tp_rank = 0
43-
self.tp_size = 1
44-
45-
def _should_load_weights(self):
46-
if self.config.get("device_mesh") is None:
47-
return True
48-
if dist.is_initialized() and self.use_tp:
49-
return dist.get_rank() == 0
50-
return super()._should_load_weights()
51-
52-
def _load_ckpt(self, unified_dtype, sensitive_layer):
53-
if not self.use_tp:
54-
return super()._load_ckpt(unified_dtype, sensitive_layer)
55-
original_device = self.device
56-
self.device = torch.device("cpu")
57-
try:
58-
return super()._load_ckpt(unified_dtype, sensitive_layer)
59-
finally:
60-
self.device = original_device
61-
62-
def _load_quant_ckpt(self, unified_dtype, sensitive_layer):
63-
if not self.use_tp:
64-
return super()._load_quant_ckpt(unified_dtype, sensitive_layer)
65-
original_device = self.device
66-
self.device = torch.device("cpu")
67-
try:
68-
return super()._load_quant_ckpt(unified_dtype, sensitive_layer)
69-
finally:
70-
self.device = original_device
71-
72-
def _rank_device(self):
73-
ai_device = global_var.AI_DEVICE
74-
if ai_device is None:
75-
return torch.device("cpu")
76-
if dist.is_initialized():
77-
return torch.device(f"{ai_device}:{dist.get_rank()}")
78-
return torch.device(ai_device)
79-
80-
def _sync_device(self):
81-
ai_device = global_var.AI_DEVICE
82-
device_module = getattr(torch, ai_device, None) if ai_device else None
83-
if device_module is not None and hasattr(device_module, "synchronize"):
84-
device_module.synchronize()
85-
86-
def _load_weights_from_rank0(self, weight_dict, is_weight_loader):
87-
if not self.use_tp:
88-
return super()._load_weights_from_rank0(weight_dict, is_weight_loader)
89-
if self.cpu_offload:
90-
raise NotImplementedError("Flux2 tensor parallel weight loading does not support cpu_offload yet.")
91-
92-
global_src_rank = 0
93-
target_device = self._rank_device()
94-
95-
if is_weight_loader:
96-
processed_weight_dict = {}
97-
meta_dict = {}
98-
processed_bias_keys = set()
99-
for key, tensor in weight_dict.items():
100-
split_type = self._get_split_type(key)
101-
if key.endswith(".weight") and split_type is not None:
102-
split_weights = self._split_weight_for_tp(key, tensor, self.tp_size)
103-
for rank_idx, split_weight in enumerate(split_weights):
104-
rank_key = f"{key}__tp_rank_{rank_idx}"
105-
processed_weight_dict[rank_key] = split_weight.contiguous()
106-
meta_dict[key] = {"shape": split_weights[0].shape, "dtype": split_weights[0].dtype, "is_tp": True}
107-
108-
bias_key = key.replace(".weight", ".bias")
109-
if bias_key in weight_dict and split_type in ("col", "ff_fused_col", "single_fused_col"):
110-
bias_splits = self._split_bias_for_tp(bias_key, weight_dict[bias_key], split_type, self.tp_size)
111-
for rank_idx, split_bias in enumerate(bias_splits):
112-
processed_weight_dict[f"{bias_key}__tp_rank_{rank_idx}"] = split_bias.contiguous()
113-
meta_dict[bias_key] = {"shape": bias_splits[0].shape, "dtype": bias_splits[0].dtype, "is_tp": True}
114-
processed_bias_keys.add(bias_key)
115-
elif key not in processed_bias_keys:
116-
processed_weight_dict[key] = tensor
117-
meta_dict[key] = {"shape": tensor.shape, "dtype": tensor.dtype, "is_tp": False}
118-
119-
obj_list = [meta_dict]
120-
dist.broadcast_object_list(obj_list, src=global_src_rank)
121-
synced_meta_dict = obj_list[0]
122-
weight_dict = processed_weight_dict
123-
else:
124-
obj_list = [None]
125-
dist.broadcast_object_list(obj_list, src=global_src_rank)
126-
synced_meta_dict = obj_list[0]
127-
128-
distributed_weight_dict = {key: torch.empty(meta["shape"], dtype=meta["dtype"], device=target_device) for key, meta in synced_meta_dict.items()}
129-
dist.barrier()
130-
131-
for key in sorted(synced_meta_dict.keys()):
132-
meta = synced_meta_dict[key]
133-
if meta.get("is_tp", False):
134-
for rank_idx in range(self.tp_size):
135-
if is_weight_loader:
136-
src_tensor = weight_dict[f"{key}__tp_rank_{rank_idx}"].to(target_device, non_blocking=True)
137-
else:
138-
src_tensor = torch.empty(meta["shape"], dtype=meta["dtype"], device=target_device)
139-
dist.broadcast(src_tensor, src=global_src_rank)
140-
if rank_idx == self.tp_rank:
141-
distributed_weight_dict[key].copy_(src_tensor, non_blocking=True)
142-
del src_tensor
143-
else:
144-
if is_weight_loader:
145-
distributed_weight_dict[key].copy_(weight_dict[key].to(target_device, non_blocking=True), non_blocking=True)
146-
dist.broadcast(distributed_weight_dict[key], src=global_src_rank)
147-
148-
self._sync_device()
149-
return distributed_weight_dict
150-
151-
def _get_split_type(self, key):
152-
if ".norm_" in key:
153-
return None
154-
if key.endswith(".weight") and "single_transformer_blocks." in key and ".attn.to_qkv_mlp_proj." in key:
155-
return "single_fused_col"
156-
if key.endswith(".weight") and "single_transformer_blocks." in key and ".attn.to_out." in key:
157-
return "single_fused_row"
158-
if key.endswith(".weight") and (".ff.linear_in." in key or ".ff_context.linear_in." in key):
159-
return "ff_fused_col"
160-
col_patterns = (
161-
".attn.to_q.",
162-
".attn.to_k.",
163-
".attn.to_v.",
164-
".attn.add_q_proj.",
165-
".attn.add_k_proj.",
166-
".attn.add_v_proj.",
167-
)
168-
row_patterns = (
169-
".attn.to_out.0.",
170-
".attn.to_add_out.",
171-
".ff.linear_out.",
172-
".ff_context.linear_out.",
173-
)
174-
if any(pattern in key for pattern in col_patterns):
175-
return "col"
176-
if any(pattern in key for pattern in row_patterns):
177-
return "row"
178-
return None
179-
180-
def _split_bias_for_tp(self, key, bias, split_type, tp_size):
181-
if split_type == "col":
182-
assert bias.shape[0] % tp_size == 0, f"bias dimension ({bias.shape[0]}) must be divisible by tp_size ({tp_size}) for {key}"
183-
return list(torch.chunk(bias, tp_size, dim=0))
184-
185-
if split_type == "ff_fused_col":
186-
assert bias.shape[0] % 2 == 0, f"invalid fused SwiGLU bias dim for {key}: {bias.shape[0]}"
187-
ffn_dim = bias.shape[0] // 2
188-
assert ffn_dim % tp_size == 0, f"ffn_dim ({ffn_dim}) must be divisible by tp_size ({tp_size}) for {key}"
189-
gate, up = torch.split(bias, [ffn_dim, ffn_dim], dim=0)
190-
gate_chunks = torch.chunk(gate, tp_size, dim=0)
191-
up_chunks = torch.chunk(up, tp_size, dim=0)
192-
return [torch.cat([gate_chunks[rank_idx], up_chunks[rank_idx]], dim=0) for rank_idx in range(tp_size)]
193-
194-
if split_type == "single_fused_col":
195-
inner_dim = self.config["num_attention_heads"] * self.config["attention_head_dim"]
196-
ffn_dim_twice = bias.shape[0] - 3 * inner_dim
197-
assert ffn_dim_twice > 0 and ffn_dim_twice % 2 == 0, f"invalid fused qkv/mlp bias dim for {key}: {bias.shape[0]}"
198-
ffn_dim = ffn_dim_twice // 2
199-
assert inner_dim % tp_size == 0, f"inner_dim ({inner_dim}) must be divisible by tp_size ({tp_size}) for {key}"
200-
assert ffn_dim % tp_size == 0, f"ffn_dim ({ffn_dim}) must be divisible by tp_size ({tp_size}) for {key}"
201-
q, k, v, mlp_1, mlp_2 = torch.split(bias, [inner_dim, inner_dim, inner_dim, ffn_dim, ffn_dim], dim=0)
202-
chunks = [torch.chunk(part, tp_size, dim=0) for part in (q, k, v, mlp_1, mlp_2)]
203-
return [torch.cat([part_chunks[rank_idx] for part_chunks in chunks], dim=0) for rank_idx in range(tp_size)]
204-
205-
raise ValueError(f"Unsupported Flux2 TP bias split type {split_type} for {key}")
206-
207-
def _split_weight_for_tp(self, key, weight, tp_size):
208-
split_type = self._get_split_type(key)
209-
if split_type is None:
210-
return [weight] * tp_size
211-
212-
if split_type == "col":
213-
assert weight.shape[0] % tp_size == 0, f"out_dim ({weight.shape[0]}) must be divisible by tp_size ({tp_size}) for {key}"
214-
return list(torch.chunk(weight, tp_size, dim=0))
215-
216-
if split_type == "row":
217-
assert weight.shape[1] % tp_size == 0, f"in_dim ({weight.shape[1]}) must be divisible by tp_size ({tp_size}) for {key}"
218-
return list(torch.chunk(weight, tp_size, dim=1))
219-
220-
if split_type == "ff_fused_col":
221-
assert weight.shape[0] % 2 == 0, f"invalid fused SwiGLU out_dim for {key}: {weight.shape[0]}"
222-
ffn_dim = weight.shape[0] // 2
223-
assert ffn_dim % tp_size == 0, f"ffn_dim ({ffn_dim}) must be divisible by tp_size ({tp_size}) for {key}"
224-
gate, up = torch.split(weight, [ffn_dim, ffn_dim], dim=0)
225-
gate_chunks = torch.chunk(gate, tp_size, dim=0)
226-
up_chunks = torch.chunk(up, tp_size, dim=0)
227-
return [torch.cat([gate_chunks[rank_idx], up_chunks[rank_idx]], dim=0) for rank_idx in range(tp_size)]
228-
229-
inner_dim = self.config["num_attention_heads"] * self.config["attention_head_dim"]
230-
if split_type == "single_fused_col":
231-
ffn_dim_twice = weight.shape[0] - 3 * inner_dim
232-
assert ffn_dim_twice > 0 and ffn_dim_twice % 2 == 0, f"invalid fused qkv/mlp out_dim for {key}: {weight.shape[0]}"
233-
ffn_dim = ffn_dim_twice // 2
234-
assert inner_dim % tp_size == 0, f"inner_dim ({inner_dim}) must be divisible by tp_size ({tp_size}) for {key}"
235-
assert ffn_dim % tp_size == 0, f"ffn_dim ({ffn_dim}) must be divisible by tp_size ({tp_size}) for {key}"
236-
q, k, v, mlp_1, mlp_2 = torch.split(weight, [inner_dim, inner_dim, inner_dim, ffn_dim, ffn_dim], dim=0)
237-
return [
238-
torch.cat(
239-
[
240-
torch.chunk(q, tp_size, dim=0)[rank_idx],
241-
torch.chunk(k, tp_size, dim=0)[rank_idx],
242-
torch.chunk(v, tp_size, dim=0)[rank_idx],
243-
torch.chunk(mlp_1, tp_size, dim=0)[rank_idx],
244-
torch.chunk(mlp_2, tp_size, dim=0)[rank_idx],
245-
],
246-
dim=0,
247-
)
248-
for rank_idx in range(tp_size)
249-
]
250-
251-
if split_type == "single_fused_row":
252-
ffn_dim = weight.shape[1] - inner_dim
253-
assert ffn_dim > 0, f"invalid fused output in_dim for {key}: {weight.shape[1]}"
254-
assert inner_dim % tp_size == 0, f"inner_dim ({inner_dim}) must be divisible by tp_size ({tp_size}) for {key}"
255-
assert ffn_dim % tp_size == 0, f"ffn_dim ({ffn_dim}) must be divisible by tp_size ({tp_size}) for {key}"
256-
attn, mlp = torch.split(weight, [inner_dim, ffn_dim], dim=1)
257-
return [
258-
torch.cat(
259-
[
260-
torch.chunk(attn, tp_size, dim=1)[rank_idx],
261-
torch.chunk(mlp, tp_size, dim=1)[rank_idx],
262-
],
263-
dim=1,
264-
)
265-
for rank_idx in range(tp_size)
266-
]
267-
268-
raise ValueError(f"Unsupported Flux2 TP split type {split_type} for {key}")
269-
27031
def _init_infer(self):
27132
self.transformer_infer = self.transformer_infer_class(self.config)
27233
self.pre_infer = self.pre_infer_class(self.config)

0 commit comments

Comments
 (0)