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

73 statements  

« prev     ^ index     » next       coverage.py v7.13.1, created at 2026-08-21 04:29 +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"""RaggedShard geometry adapters for distributed checkpoint planners.""" 

16from math import prod 

17from typing import Any, NamedTuple 

18 

19from hyper_parallel.core.distributed_checkpoint.metadata import ( 

20 ChunkStorageMetadata, 

21 MetadataIndex, 

22 TensorProperties, 

23) 

24from hyper_parallel.core.distributed_checkpoint.planner import ( 

25 WriteItem, 

26 WriteItemType, 

27) 

28from hyper_parallel.core.dtensor._ragged_utils import _compute_ragged_slice 

29from hyper_parallel.core.dtensor.dtensor import DTensor 

30 

31 

32class RaggedCheckpointBox(NamedTuple): 

33 """One regular global box backed by a contiguous local flat interval.""" 

34 

35 offsets: tuple[int, ...] 

36 sizes: tuple[int, ...] 

37 local_flat_start: int 

38 local_flat_end: int 

39 

40 

41def _decompose_flat_interval( 

42 shape: tuple[int, ...], 

43 flat_start: int, 

44 flat_end: int, 

45) -> tuple[tuple[tuple[int, ...], tuple[int, ...]], ...]: 

46 """Decompose a row-major flat interval into ordered N-D boxes.""" 

47 total_numel = prod(shape) 

48 if not shape: 

49 raise ValueError("Ragged checkpoint geometry requires a non-scalar global shape") 

50 if flat_start < 0 or flat_end < flat_start or flat_end > total_numel: 

51 raise ValueError( 

52 "Invalid flat interval for Ragged checkpoint geometry, " 

53 f"got interval=({flat_start}, {flat_end}), shape={shape!r}" 

54 ) 

55 if flat_start == flat_end: 

56 return () 

57 

58 boxes: list[tuple[tuple[int, ...], tuple[int, ...]]] = [] 

59 

60 def _decompose_axis( 

61 axis: int, 

62 start: int, 

63 end: int, 

64 prefix_offsets: tuple[int, ...], 

65 ) -> None: 

66 if axis == len(shape) - 1: 

67 boxes.append( 

68 ( 

69 prefix_offsets + (start,), 

70 (1,) * len(prefix_offsets) + (end - start,), 

71 ) 

72 ) 

73 return 

74 

75 stride = prod(shape[axis + 1:]) 

76 start_block, start_remainder = divmod(start, stride) 

77 end_block = (end - 1) // stride 

78 if start_block == end_block: 

79 _decompose_axis( 

80 axis + 1, 

81 start_remainder, 

82 start_remainder + end - start, 

83 prefix_offsets + (start_block,), 

84 ) 

85 return 

86 

87 complete_start = start_block 

88 if start_remainder: 

89 _decompose_axis( 

90 axis + 1, 

91 start_remainder, 

92 stride, 

93 prefix_offsets + (start_block,), 

94 ) 

95 complete_start += 1 

96 

97 complete_end, end_remainder = divmod(end, stride) 

98 if complete_start < complete_end: 

99 boxes.append( 

100 ( 

101 prefix_offsets 

102 + (complete_start,) 

103 + (0,) * (len(shape) - axis - 1), 

104 (1,) * len(prefix_offsets) 

105 + (complete_end - complete_start,) 

106 + shape[axis + 1:], 

107 ) 

108 ) 

109 

110 if end_remainder: 

111 _decompose_axis( 

112 axis + 1, 

113 0, 

114 end_remainder, 

115 prefix_offsets + (complete_end,), 

116 ) 

117 

118 _decompose_axis(0, flat_start, flat_end, ()) 

119 return tuple(boxes) 

120 

121 

122def compute_ragged_boxes(tensor: DTensor) -> tuple[RaggedCheckpointBox, ...]: 

123 """Return ordered N-D boxes covering one RaggedShard local flat tensor.""" 

124 layout = tensor.layout 

125 if layout.ragged_shard is None: 

126 raise ValueError("compute_ragged_boxes requires a RaggedShard DTensor") 

127 

128 global_shape = tuple(tensor.shape) 

129 ragged_slice = _compute_ragged_slice(global_shape, layout) 

130 raw_boxes = _decompose_flat_interval( 

131 global_shape, 

132 ragged_slice.flat_start, 

133 ragged_slice.flat_end, 

134 ) 

135 boxes: list[RaggedCheckpointBox] = [] 

136 local_flat_offset = 0 

137 for offsets, sizes in raw_boxes: 

138 box_numel = prod(sizes) 

139 boxes.append( 

140 RaggedCheckpointBox( 

141 offsets=offsets, 

142 sizes=sizes, 

143 local_flat_start=local_flat_offset, 

144 local_flat_end=local_flat_offset + box_numel, 

145 ) 

146 ) 

147 local_flat_offset += box_numel 

148 

149 if local_flat_offset != ragged_slice.local_numel: 

150 raise ValueError( 

151 "Ragged checkpoint boxes do not cover the local flat tensor, " 

152 f"covered={local_flat_offset}, expected={ragged_slice.local_numel}" 

153 ) 

154 return tuple(boxes) 

155 

156 

157def create_ragged_write_items(fqn: str, tensor: DTensor) -> list[WriteItem]: 

158 """Create one standard N-D checkpoint write item per RaggedShard box.""" 

159 local_tensor = tensor.to_local() 

160 dtype_str = str(local_tensor.dtype) if hasattr(local_tensor, "dtype") else "unknown" 

161 properties = TensorProperties(dtype=dtype_str) 

162 items: list[WriteItem] = [] 

163 for box in compute_ragged_boxes(tensor): 

164 chunk = ChunkStorageMetadata(offsets=box.offsets, sizes=box.sizes) 

165 items.append( 

166 WriteItem( 

167 index=MetadataIndex(fqn=fqn, offset=box.offsets, index=None), 

168 type=WriteItemType.TENSOR, 

169 tensor_data={ 

170 "chunk": chunk, 

171 "properties": properties, 

172 "size": tuple(tensor.shape), 

173 }, 

174 ) 

175 ) 

176 return items 

177 

178 

179def get_ragged_box_tensor(tensor: DTensor, index: MetadataIndex) -> Any: 

180 """Return the local flat view corresponding to one global N-D box.""" 

181 requested_offset = tuple(index.offset) if index.offset is not None else None 

182 for box in compute_ragged_boxes(tensor): 

183 if box.offsets == requested_offset: 

184 local_flat = tensor.to_local().reshape((-1,)) 

185 return local_flat[ 

186 box.local_flat_start:box.local_flat_end 

187 ].reshape(box.sizes) 

188 raise ValueError( 

189 "Ragged checkpoint box was not found in the local DTensor, " 

190 f"fqn={index.fqn!r}, offset={index.offset!r}" 

191 )