Coverage for  / home / jenkins / .local / lib / python3.10 / site-packages / hyper_parallel / core / distributed_checkpoint / standard_planner.py: 80%

284 statements  

« prev     ^ index     » next       coverage.py v7.13.1, created at 2026-08-22 04:23 +0800

1# Copyright 2026 Huawei Technologies Co., Ltd 

2# 

3# Licensed under the Apache License, Version 2.0 (the "License"); 

4# you may not use this file except in compliance with the License. 

5# You may obtain a copy of the License at 

6# 

7# http://www.apache.org/licenses/LICENSE-2.0 

8# 

9# Unless required by applicable law or agreed to in writing, software 

10# distributed under the License is distributed on an "AS IS" BASIS, 

11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 

12# See the License for the specific language governing permissions and 

13# limitations under the License. 

14# ============================================================================ 

15"""Standard planner implementations for checkpoint save and load.""" 

16from dataclasses import dataclass 

17import dataclasses 

18import pickle 

19from typing import Any, Optional, Union 

20 

21from hyper_parallel.core.distributed_checkpoint.metadata import ( 

22 CHUNK_INFO, 

23 Metadata, 

24 MetadataIndex, 

25 ChunkStorageMetadata, 

26 ChunkInfo, 

27 TensorStorageMetadata, 

28 TensorProperties, 

29 BytesStorageMetadata 

30) 

31from hyper_parallel.core.distributed_checkpoint.planner import ( 

32 SavePlan, 

33 SavePlanner, 

34 LoadPlan, 

35 LoadPlanner, 

36 WriteItem, 

37 WriteItemType, 

38 ReadItem, 

39 LoadItemType 

40) 

41from hyper_parallel.core.distributed_checkpoint.reshard import infer_slice_area_by_rank, infer_intersection 

42from hyper_parallel.core.distributed_checkpoint.ragged_utils import ( 

43 create_ragged_write_items, 

44 get_ragged_box_tensor, 

45) 

46from hyper_parallel.core.distributed_checkpoint.util import ( 

47 narrow_tensor_by_index, 

48 chunk_to_area, 

49 create_chunk_list_for_tensor, 

50 remove_redundant_plans, 

51 flatten_state_dict, 

52 set_element, 

53) 

54from hyper_parallel.core.dtensor.dtensor import DTensor 

55from hyper_parallel.core.dtensor.layout import Layout 

56from hyper_parallel.platform import get_platform 

57 

58platform = get_platform() 

59Tensor = platform.Tensor 

60 

61 

62@dataclass(frozen=True) 

63class CachedSaveResult: 

64 """Cached finalized save result keyed by planner cache namespace.""" 

65 

66 final_plan: SavePlan 

67 metadata: Metadata 

68 

69 

70class StandardSavePlanner(SavePlanner): 

71 """Standard implementation of SavePlanner for distributed checkpoint saving.""" 

72 

73 _cached_save_result: dict[str, CachedSaveResult] = {} 

74 

75 def __init__( 

76 self, 

77 enable_plan_caching: bool = True, 

78 remove_redundancy: bool = True, 

79 save_to_minimum_rank: bool = False, 

80 ): 

81 self.state_dict: Optional[dict[str, Any]] = None 

82 self.is_coordinator: bool = False 

83 self.rank: int = 0 

84 self.remove_redundancy: bool = remove_redundancy 

85 self.save_to_minimum_rank: bool = save_to_minimum_rank 

86 self.flatten_state_dict: bool = True 

87 self._enable_plan_caching: bool = enable_plan_caching 

88 self._default_enable_plan_caching: bool = enable_plan_caching 

89 self._cached_plans_key: str = self.__class__.__name__ 

90 

91 def configure_planner(self, state_dict: dict[str, Any], **kwargs) -> None: 

92 """ 

93 Configure planner. 

94 

95 Args: 

96 state_dict (dict[str, Any]): The state_dict to save. 

97 **kwargs: Additional keyword arguments (e.g., is_coordinator, rank, remove_redundancy, 

98 save_to_minimum_rank). 

99 """ 

100 self.is_coordinator = kwargs.get("is_coordinator", False) 

101 self.rank = kwargs.get("rank", 0) 

102 self.remove_redundancy = kwargs.get("remove_redundancy", self.remove_redundancy) 

103 self.save_to_minimum_rank = kwargs.get("save_to_minimum_rank", self.save_to_minimum_rank) 

104 self.flatten_state_dict = kwargs.get("flatten_state_dict", True) 

105 

106 use_collectives = bool(kwargs.get("use_collectives", True)) 

107 self._enable_plan_caching = bool( 

108 kwargs.get("enable_plan_caching", self._default_enable_plan_caching) 

109 ) 

110 if not use_collectives: 

111 self.remove_redundancy = False 

112 self._enable_plan_caching = False 

113 

114 if self.flatten_state_dict: 

115 state_dict, self.name_mapping = flatten_state_dict(state_dict) 

116 self.state_dict = state_dict 

117 if any( 

118 isinstance(obj, DTensor) 

119 and obj.layout is not None 

120 and obj.layout.ragged_shard is not None 

121 for obj in state_dict.values() 

122 ): 

123 self._enable_plan_caching = False 

124 self._cached_plans_key = self._build_cache_key(state_dict) 

125 

126 def _build_cache_key(self, state_dict: dict[str, Any]) -> str: 

127 """Build a stable cache namespace from sorted state_dict keys.""" 

128 return f"{self.__class__.__name__}:{'||'.join(state_dict.keys())}" 

129 

130 def build_local_plan(self) -> SavePlan: 

131 """ 

132 Create local save plan. 

133 

134 Returns: 

135 SavePlan: Local save plan containing WriteItems for this rank. 

136 """ 

137 if self.state_dict is None: 

138 raise RuntimeError("Planner not set up") 

139 

140 def compute_global_offsets(global_shape: tuple[int, ...], dtensor_layout: Layout) -> tuple[int, ...]: 

141 """ 

142 Compute the offsets of local tensor in global tensor based on layout. 

143 

144 Args: 

145 global_shape (tuple[int, ...]): Global shape of the tensor. 

146 dtensor_layout (Layout): Layout of the DTensor. 

147 

148 Returns: 

149 tuple[int, ...]: Tuple of offsets for each dimension. 

150 """ 

151 if dtensor_layout is None: 

152 # If layout is None, return all zeros (no sharding) 

153 return tuple(0 for _ in global_shape) 

154 

155 # Validate layout attributes 

156 if not hasattr(dtensor_layout, 'mesh_shape') or dtensor_layout.mesh_shape is None: 

157 raise ValueError("Layout must have mesh_shape attribute") 

158 if not hasattr(dtensor_layout, 'tensor_map') or dtensor_layout.tensor_map is None: 

159 raise ValueError("Layout must have tensor_map attribute") 

160 if not hasattr(dtensor_layout, 'rank_list') or dtensor_layout.rank_list is None: 

161 raise ValueError("Layout must have rank_list attribute") 

162 

163 current_rank = self.rank 

164 if current_rank not in dtensor_layout.rank_list: 

165 raise ValueError( 

166 f"Current rank {current_rank} not found in layout's rank_list {dtensor_layout.rank_list}") 

167 

168 inner_rank_id = dtensor_layout.rank_list.index(current_rank) 

169 # Calculate slice area using infer_slice_area_by_rank 

170 slice_area = infer_slice_area_by_rank( 

171 mesh_shape=dtensor_layout.mesh_shape, 

172 tensor_map=dtensor_layout.tensor_map, 

173 rank_id=inner_rank_id, 

174 full_shape=global_shape 

175 ) 

176 # Extract offsets (start values) from slice_area 

177 return tuple(start for start, _ in slice_area) 

178 

179 items = [] 

180 for fqn, obj in self.state_dict.items(): 

181 # Check if it's a DTensor 

182 if isinstance(obj, DTensor): 

183 if obj.layout is not None and obj.layout.ragged_shard is not None: 

184 items.extend(create_ragged_write_items(fqn, obj)) 

185 continue 

186 # Create write item for DTensor 

187 local_tensor = obj.to_local() 

188 layout = obj.layout 

189 

190 # Get chunk metadata with offsets 

191 if layout: 

192 offsets = compute_global_offsets(obj.shape, layout) 

193 else: 

194 offsets = (0,) * len(local_tensor.shape) 

195 

196 sizes = local_tensor.shape 

197 chunk = ChunkStorageMetadata(offsets=offsets, sizes=sizes) 

198 # Get tensor properties 

199 dtype_str = str(local_tensor.dtype) if hasattr(local_tensor, 'dtype') else 'unknown' 

200 properties = TensorProperties(dtype=dtype_str) 

201 # Create write item for this tensor 

202 index = MetadataIndex(fqn=fqn, offset=offsets, index=None) 

203 write_item = WriteItem( 

204 index=index, 

205 type=WriteItemType.TENSOR, 

206 tensor_data={ 

207 'chunk': chunk, 

208 'properties': properties, 

209 'size': obj.shape, 

210 } 

211 ) 

212 items.append(write_item) 

213 elif isinstance(obj, Tensor): 

214 # Create write item for platform.Tensor: build single chunk with tensor's own size 

215 dtype_str = str(obj.dtype) if hasattr(obj, 'dtype') else 'unknown' 

216 properties = TensorProperties(dtype=dtype_str) 

217 # handle Tensor with shard information 

218 if hasattr(obj, CHUNK_INFO): 

219 if not isinstance(getattr(obj, CHUNK_INFO), ChunkInfo): 

220 raise ValueError("The attr CHUNK_INFO should be a ChunkInfo instance") 

221 chunk = getattr(obj, CHUNK_INFO).chunk 

222 # Single chunk covering the whole tensor (offsets=0, sizes=shape) 

223 else: 

224 chunk = ChunkStorageMetadata( 

225 offsets=(0,) * len(obj.shape), 

226 sizes=obj.shape, 

227 ) 

228 index = MetadataIndex(fqn=fqn, offset=chunk.offsets, index=None) 

229 write_item = WriteItem( 

230 index=index, 

231 type=WriteItemType.TENSOR, 

232 tensor_data={ 

233 'chunk': chunk, 

234 'properties': properties, 

235 'size': getattr(obj, CHUNK_INFO).global_shape if hasattr(obj, CHUNK_INFO) else obj.shape, 

236 } 

237 ) 

238 items.append(write_item) 

239 else: 

240 # Handle non-tensor types (bytes, etc.) 

241 index = MetadataIndex(fqn=fqn) 

242 write_item = WriteItem( 

243 index=index, 

244 type=WriteItemType.BYTE_IO, 

245 bytes_io_data=None 

246 ) 

247 items.append(write_item) 

248 

249 plan = SavePlan(items=items) 

250 if self.flatten_state_dict: 

251 plan.planner_data = self.name_mapping 

252 return plan 

253 

254 def build_global_plan(self, all_plans: list[SavePlan]) -> tuple[list[SavePlan], Metadata]: 

255 """ 

256 Build global plan from all local plans. 

257 

258 Collects chunks from all ranks, validates consistency, and creates metadata for the checkpoint. 

259 

260 Args: 

261 all_plans (list[SavePlan]): List of local plans from all ranks. 

262 

263 Returns: 

264 tuple[list[SavePlan], Metadata]: Updated plans and checkpoint metadata. 

265 """ 

266 # Deduplicate plans if redundancy removal is enabled 

267 if self.remove_redundancy and len(all_plans) > 1: 

268 all_plans = remove_redundant_plans(all_plans, save_to_minimum_rank=self.save_to_minimum_rank) 

269 

270 # Collect all write items by FQN 

271 fqn_to_chunks: dict[str, list[ChunkStorageMetadata]] = {} 

272 fqn_to_properties: dict[str, TensorProperties] = {} 

273 fqn_to_size: dict[str, tuple] = {} 

274 state_dict_metadata: dict[str, Union[TensorStorageMetadata, BytesStorageMetadata]] = {} 

275 

276 final_global_plans: list[SavePlan] = [] 

277 for plan in all_plans: 

278 with_index_items = [] 

279 for item in plan.items: 

280 if item.type == WriteItemType.TENSOR and item.tensor_data: 

281 fqn = item.index.fqn 

282 chunk = item.tensor_data['chunk'] 

283 properties = item.tensor_data['properties'] 

284 size = item.tensor_data['size'] 

285 

286 # Validate consistency across ranks 

287 if fqn in fqn_to_chunks and (fqn_to_properties[fqn] != properties or fqn_to_size[fqn] != size): 

288 raise ValueError(f"The {fqn} in different rank has different properties and size.") 

289 

290 # Initialize FQN entry if not exists 

291 if fqn not in fqn_to_chunks: 

292 fqn_to_properties[fqn] = properties 

293 fqn_to_size[fqn] = size 

294 fqn_to_chunks[fqn] = [] 

295 

296 # Append chunk and set index (platform.Tensor has exactly one chunk) 

297 new_index = dataclasses.replace(item.index, index=len(fqn_to_chunks[fqn])) 

298 with_index_item = dataclasses.replace(item, index=new_index) 

299 with_index_items.append(with_index_item) 

300 fqn_to_chunks[fqn].append(chunk) 

301 

302 elif item.type == WriteItemType.BYTE_IO: 

303 with_index_items.append(item) 

304 state_dict_metadata[item.index.fqn] = BytesStorageMetadata() 

305 else: 

306 raise ValueError(f"Unsupported write item type: {item.type}") 

307 

308 final_global_plans.append(dataclasses.replace(plan, items=with_index_items)) 

309 

310 # Create metadata for all tensors 

311 for fqn, chunks in fqn_to_chunks.items(): 

312 state_dict_metadata[fqn] = TensorStorageMetadata( 

313 properties=fqn_to_properties[fqn], 

314 size=fqn_to_size[fqn], 

315 chunks=chunks 

316 ) 

317 

318 metadata = Metadata(state_dict_metadata=state_dict_metadata) 

319 if self.flatten_state_dict: 

320 merged_mapping = {} 

321 for p in all_plans: 

322 merged_mapping.update(p.planner_data) 

323 metadata.planner_data = merged_mapping 

324 return final_global_plans, metadata 

325 

326 def finalize_plan(self, plan: SavePlan) -> SavePlan: 

327 """ 

328 Finalize the plan. 

329 

330 Args: 

331 plan (SavePlan): Plan to finalize. 

332 

333 Returns: 

334 SavePlan: Finalized plan. 

335 """ 

336 return plan 

337 

338 def get_cached(self) -> Optional[CachedSaveResult]: 

339 """Return cached finalized plan and metadata when plan caching is enabled.""" 

340 if ( 

341 not self._enable_plan_caching 

342 or self._cached_plans_key not in StandardSavePlanner._cached_save_result 

343 ): 

344 return None 

345 return StandardSavePlanner._cached_save_result[self._cached_plans_key] 

346 

347 def cache_result(self, final_plan: SavePlan, metadata: Metadata) -> None: 

348 """Store finalized plan and metadata in the class-level planner cache.""" 

349 if not self._enable_plan_caching: 

350 return 

351 StandardSavePlanner._cached_save_result[self._cached_plans_key] = CachedSaveResult( 

352 final_plan=final_plan, 

353 metadata=metadata, 

354 ) 

355 

356 def get_data(self, item: WriteItem) -> Any: 

357 """ 

358 Get current runtime data from state_dict for a write item. 

359 

360 Args: 

361 item (WriteItem): Write item describing what to write. 

362 

363 Returns: 

364 Any: Runtime object to be written. 

365 """ 

366 if self.state_dict is None: 

367 raise RuntimeError("Planner not set up") 

368 fqn = item.index.fqn 

369 if fqn not in self.state_dict: 

370 raise KeyError(f"Key {fqn} not found in state_dict") 

371 obj = self.state_dict[fqn] 

372 if item.type == WriteItemType.TENSOR: 

373 if isinstance(obj, DTensor): 

374 if obj.layout is not None and obj.layout.ragged_shard is not None: 

375 return get_ragged_box_tensor(obj, item.index).detach().cpu() 

376 return obj.to_local().detach().cpu() 

377 if isinstance(obj, Tensor): 

378 return obj.detach().cpu() 

379 raise TypeError(f"Write item {fqn} expected tensor-like object, got {type(obj)}") 

380 if item.type == WriteItemType.BYTE_IO: 

381 return obj 

382 raise TypeError(f"Unsupported write item type: {item.type}") 

383 

384 

385def create_read_items_for_chunk_list( 

386 fqn: str, 

387 checkpoint_md: TensorStorageMetadata, 

388 local_chunks: list[ChunkStorageMetadata], 

389) -> list[ReadItem]: 

390 """ 

391 Create ReadItems by matching local chunks (what this rank needs) with 

392 saved chunks (checkpoint_md.chunks), including resharding overlaps. 

393 

394 Mirrors torch create_read_items_for_chunk_list behavior. 

395 

396 Args: 

397 fqn (str): Fully qualified name of the tensor. 

398 checkpoint_md (TensorStorageMetadata): Tensor storage metadata from checkpoint. 

399 local_chunks (list[ChunkStorageMetadata]): List of local chunks needed by this rank. 

400 

401 Returns: 

402 list[ReadItem]: List of ReadItems for loading the required data. 

403 """ 

404 read_items: list[ReadItem] = [] 

405 saved_chunks = checkpoint_md.chunks 

406 if not local_chunks or not saved_chunks: 

407 return read_items 

408 

409 for local_idx, local_chunk in enumerate(local_chunks): 

410 local_area = chunk_to_area(local_chunk) 

411 for storage_idx, storage_chunk in enumerate(saved_chunks): 

412 saved_area = chunk_to_area(storage_chunk) 

413 overlap = infer_intersection(local_area, saved_area) 

414 if overlap is None: 

415 continue 

416 

417 dest_offsets = tuple(overlap[i][0] - local_chunk.offsets[i] for i in range(len(overlap))) 

418 storage_offsets = tuple(overlap[i][0] - storage_chunk.offsets[i] for i in range(len(overlap))) 

419 lengths = tuple(overlap[i][1] - overlap[i][0] for i in range(len(overlap))) 

420 

421 read_items.append( 

422 ReadItem( 

423 type=LoadItemType.TENSOR, 

424 dest_index=MetadataIndex(fqn=fqn, offset=local_chunk.offsets, index=local_idx), 

425 dest_offsets=dest_offsets, 

426 storage_index=MetadataIndex(fqn=fqn, offset=storage_chunk.offsets, index=storage_idx), 

427 storage_offsets=storage_offsets, 

428 lengths=lengths, 

429 ) 

430 ) 

431 return read_items 

432 

433 

434class StandardLoadPlanner(LoadPlanner): 

435 """ 

436 Standard implementation of LoadPlanner. 

437 

438 Iterate state_dict and creates load plans via chunk list for resharding support. 

439 """ 

440 

441 def __init__(self, allow_partial_load: bool = False): 

442 """ 

443 Args: 

444 allow_partial_load (bool): If True, allow loading when checkpoint has fewer keys than state_dict. 

445 Default False. 

446 """ 

447 self.state_dict: Optional[dict[str, Any]] = None 

448 self.metadata: Optional[Metadata] = None 

449 self.is_coordinator: bool = False 

450 self.rank: int = 0 

451 self.allow_partial_load = allow_partial_load 

452 self.flatten_state_dict: bool = True 

453 

454 def configure_planner(self, state_dict: dict[str, Any], metadata: Metadata, **kwargs) -> None: 

455 """ 

456 Configure planner with state dict and metadata. 

457 

458 Args: 

459 state_dict (dict[str, Any]): The state_dict to load into (modified in-place). 

460 metadata (Metadata): Checkpoint metadata. 

461 **kwargs: Additional keyword arguments (e.g., is_coordinator, rank). 

462 """ 

463 self.state_dict = state_dict 

464 self.metadata = metadata 

465 self.is_coordinator = kwargs.get("is_coordinator", False) 

466 self.rank = kwargs.get("rank", 0) 

467 self.flatten_state_dict = kwargs.get("flatten_state_dict", True) 

468 self.original_state_dict = state_dict 

469 if self.flatten_state_dict: 

470 state_dict, self.name_mapping = flatten_state_dict(state_dict) 

471 self.state_dict = state_dict 

472 

473 def build_local_plan(self) -> LoadPlan: 

474 """ 

475 Build local load plan. 

476 

477 Iterate state_dict and creates load plans via chunk list for resharding support. 

478 

479 Returns: 

480 LoadPlan: Local load plan containing ReadItems for this rank. 

481 """ 

482 if self.state_dict is None or self.metadata is None: 

483 raise RuntimeError("Planner not configured") 

484 

485 requests: list[ReadItem] = [] 

486 strict = not self.allow_partial_load 

487 for fqn, obj in self.state_dict.items(): 

488 if fqn not in self.metadata.state_dict_metadata: 

489 if fqn.endswith(('matched_adamw_rms', 'step')): 

490 continue 

491 if strict: 

492 raise RuntimeError(f"Missing key in checkpoint state_dict: {fqn}.") 

493 continue 

494 md = self.metadata.state_dict_metadata[fqn] 

495 if isinstance(md, TensorStorageMetadata): 

496 obj_size = getattr(obj, CHUNK_INFO).global_shape if hasattr(obj, CHUNK_INFO) \ 

497 else getattr(obj, "shape", None) 

498 if obj_size is None or md.size != tuple(obj_size): 

499 raise ValueError( 

500 f"Size mismatch between saved {md.size} and current: {obj_size} for {fqn}", 

501 ) 

502 if isinstance(obj, DTensor): 

503 layout = getattr(obj, "layout", None) 

504 rank_list = getattr(layout, "rank_list", None) if layout else None 

505 if rank_list is None and layout is not None: 

506 rank_list = getattr(layout, "_rank_list", None) 

507 if layout is not None and rank_list is not None: 

508 if get_platform().get_rank() not in rank_list: 

509 continue 

510 # Both DTensor and platform.Tensor: create local chunks and read items 

511 local_chunks = create_chunk_list_for_tensor(obj) 

512 requests += create_read_items_for_chunk_list(fqn, md, local_chunks) 

513 else: 

514 requests.append( 

515 ReadItem( 

516 type=LoadItemType.BYTE_IO, 

517 dest_index=MetadataIndex(fqn=fqn), 

518 dest_offsets=(0,), 

519 storage_index=MetadataIndex(fqn=fqn), 

520 storage_offsets=(0,), 

521 lengths=(0,), 

522 ) 

523 ) 

524 return LoadPlan(items=requests) 

525 

526 def build_global_plan(self, all_plans: list[LoadPlan]) -> list[LoadPlan]: 

527 """ 

528 Build global plan from all local plans. 

529 

530 For now, returns plans as-is. In a more sophisticated implementation, you might need to coordinate across ranks. 

531 

532 Args: 

533 all_plans (list[LoadPlan]): List of local plans from all ranks. 

534 

535 Returns: 

536 list[LoadPlan]: Global plans (currently returns plans as-is). 

537 """ 

538 return all_plans 

539 

540 def finalize_plan(self, plan: LoadPlan) -> LoadPlan: 

541 """ 

542 Finalize the plan (no-op for default implementation). 

543 

544 Args: 

545 plan (LoadPlan): Plan to finalize. 

546 

547 Returns: 

548 LoadPlan: Finalized plan. 

549 """ 

550 return plan 

551 

552 def acquire_tensor(self, read_item: ReadItem) -> Any: 

553 """ 

554 Acquire the destination slice (narrow view) for this read_item. 

555 

556 StorageReader uses this to copy loaded data into the correct region. 

557 Torch-aligned behavior. 

558 

559 Args: 

560 read_item (ReadItem): The read item specifying what to load. 

561 

562 Returns: 

563 Any: The destination tensor slice where data should be written 

564 (tensor-like object). 

565 """ 

566 if self.state_dict is None: 

567 raise RuntimeError("Planner not configured") 

568 

569 fqn = read_item.dest_index.fqn 

570 if fqn not in self.state_dict: 

571 raise KeyError(f"Key {fqn} not found in state_dict") 

572 

573 target = self.state_dict[fqn] 

574 if ( 

575 isinstance(target, DTensor) 

576 and target.layout is not None 

577 and target.layout.ragged_shard is not None 

578 ): 

579 box_tensor = get_ragged_box_tensor(target, read_item.dest_index) 

580 return narrow_tensor_by_index( 

581 box_tensor, 

582 read_item.dest_offsets, 

583 read_item.lengths, 

584 ) 

585 

586 local_tensor = target.to_local().detach() if isinstance(target, DTensor) else target.detach() 

587 return narrow_tensor_by_index( 

588 local_tensor, 

589 read_item.dest_offsets, 

590 read_item.lengths, 

591 ) 

592 

593 def apply_tensor(self, read_item: ReadItem, tensor: Any) -> None: 

594 """ 

595 Apply tensor after reading. 

596 

597 After read_data copies into the slice, this is no-op when tensor is the 

598 same slice. When the backend has no copy_ (e.g. mindspore), read_data 

599 passes the loaded slice here; we copy it into the destination slice. 

600 

601 Args: 

602 read_item (ReadItem): The read item that was processed. 

603 tensor (Any): The tensor data to apply (tensor-like object). 

604 """ 

605 if tensor is None: 

606 return 

607 dest_slice = self.acquire_tensor(read_item) 

608 if dest_slice is tensor: 

609 return 

610 if hasattr(dest_slice, "copy_"): 

611 dest_slice.copy_(tensor) 

612 else: 

613 # Fallback: assign into state_dict if supported 

614 dest_slice[...] = tensor 

615 

616 def apply_bytes(self, read_item: ReadItem, value: bytes) -> None: 

617 """ 

618 Load bytes data into state_dict. 

619 

620 Args: 

621 read_item (ReadItem): The read item specifying the destination. 

622 value (bytes): The bytes data to deserialize and load. 

623 """ 

624 if self.state_dict is None: 

625 raise RuntimeError("Planner not set up") 

626 

627 fqn = read_item.dest_index.fqn 

628 # Deserialize bytes 

629 obj = pickle.loads(value) 

630 self.state_dict[fqn] = obj 

631 if self.flatten_state_dict: 

632 set_element(self.original_state_dict, self.name_mapping[fqn], obj) 

633 

634 

635 

636class _DcpMergeLoadPlanner(StandardLoadPlanner): 

637 """Load planner that builds distributed checkpoint from dcp into fully ``state_dict`` (in-place).""" 

638 

639 def __init__(self) -> None: 

640 super().__init__() 

641 

642 def configure_planner(self, state_dict: dict[str, Any], metadata: Metadata, **kwargs) -> None: 

643 if len(state_dict) > 0: 

644 raise ValueError( 

645 "state_dict must be empty for _DcpMergeLoadPlanner; " 

646 "it is populated in-place from checkpoint metadata." 

647 ) 

648 

649 if metadata is None: 

650 raise ValueError("metadata must not be None for _DcpMergeLoadPlanner.") 

651 

652 self.is_coordinator = kwargs.get("is_coordinator", False) 

653 for k, v in metadata.state_dict_metadata.items(): 

654 if isinstance(v, TensorStorageMetadata): 

655 v = platform.empty( 

656 platform.list_to_size(v.size), 

657 dtype=platform.str_to_dtype(v.properties.dtype), 

658 ) 

659 

660 state_dict[k] = v 

661 if metadata.planner_data is not None and k in metadata.planner_data: 

662 set_element(state_dict, metadata.planner_data[k], v) 

663 

664 super().configure_planner( 

665 state_dict, 

666 metadata, 

667 is_coordinator=self.is_coordinator, 

668 flatten_state_dict=True, 

669 )