Coverage for  / home / jenkins / .local / lib / python3.10 / site-packages / hyper_parallel / auto_parallel / sapp_nd / memory_estimation / _hook_manager.py: 90%

254 statements  

« prev     ^ index     » next       coverage.py v7.13.1, created at 2026-10-25 05:45 +0800

1# Copyright 2025-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"""hook manager module""" 

16from __future__ import annotations 

17from typing import TYPE_CHECKING 

18import ast 

19import textwrap 

20import inspect 

21from hyper_parallel.auto_parallel.sapp_nd.nd.common.config import Config 

22from hyper_parallel.auto_parallel.sapp_nd.nd.common.layer_type import LayerType 

23from hyper_parallel.auto_parallel.sapp_nd.nd.common.cost_model_preprocess import strategy_guarded 

24from hyper_parallel.auto_parallel.sapp_nd.nd.common.arch_hooks import check_and_apply_custom_hook 

25from hyper_parallel.auto_parallel.sapp_nd.memory_estimation.logger import logger 

26from hyper_parallel.auto_parallel.sapp_nd.memory_estimation._context import ( 

27 NodeEval, 

28 NodeStatEval, 

29 NodeDynEval, 

30 NodeCommEval, 

31 NodeComputeEval, 

32) 

33from hyper_parallel.auto_parallel.sapp_nd.memory_estimation.evaluators.compute import EvalExpertCompute 

34from hyper_parallel.auto_parallel.sapp_nd.memory_estimation.evaluators.head import EvalHead 

35from hyper_parallel.auto_parallel.sapp_nd.memory_estimation.evaluators.tail import EvalTail 

36from hyper_parallel.auto_parallel.sapp_nd.memory_estimation.evaluators.body import EvalBody 

37from hyper_parallel.auto_parallel.sapp_nd.memory_estimation.evaluators.layer_block import EvalAttn, EvalFFn 

38from hyper_parallel.auto_parallel.sapp_nd.memory_estimation.evaluators.layer_block import EvalNorm 

39from hyper_parallel.auto_parallel.sapp_nd.memory_estimation.evaluators.comm import EvalLayerComm 

40from hyper_parallel.auto_parallel.sapp_nd.memory_estimation.evaluators.utils import EvalUtils 

41from hyper_parallel.auto_parallel.sapp_nd.memory_estimation._backbone import _Backbone 

42from hyper_parallel.auto_parallel.sapp_nd.memory_estimation._func_tracer import _FuncTracer 

43from hyper_parallel.auto_parallel.sapp_nd.memory_estimation._context import MemType 

44 

45if TYPE_CHECKING: 

46 from typing import Callable, Any 

47 

48 

49class _HookManager(_Backbone): 

50 """Hook manager class.""" 

51 

52 def __init__(self, *args, **kwargs): 

53 super().__init__(*args, **kwargs) 

54 self.func_tracer = _FuncTracer() 

55 self.toggle_func_trace = kwargs.get("trace_fun", False) 

56 self.import_eval_yaml() 

57 self.fetch_hook_if_unimodal() 

58 

59 def fetch_hook_if_unimodal(self): 

60 """Process custom model config""" 

61 if not self._ccfg.multimodal: 

62 if not self._ccfg.hooks_dict: 

63 logger.info( 

64 "'hook_cls' not specified," 

65 "search in predefined arch_hooks" 

66 ) 

67 check_and_apply_custom_hook(self) 

68 else: 

69 hook = list(self._ccfg.hooks_dict.values())[0] 

70 hook(self) 

71 

72 def __is_valid_eval_func(self, fun: Any) -> bool: 

73 """check hook definition, return type""" 

74 if fun is None: 

75 return False 

76 if isinstance(fun, (str, int, float)): 

77 return True 

78 

79 source = inspect.getsource(fun) 

80 tree = ast.parse(textwrap.dedent(source)) 

81 for instruction in ast.walk(tree): 

82 if ( 

83 isinstance(instruction, ast.Return) 

84 and instruction.value is None 

85 ): 

86 return False 

87 return True 

88 

89 # Evaluation context setters 

90 

91 def set_passes( 

92 self, 

93 vpp_less_mem: bool = None, 

94 swap_os: bool = None, 

95 dropless_tok_factor: float = None, 

96 ) -> None: 

97 """toggle features""" 

98 if isinstance(vpp_less_mem, bool): 

99 self._ctx.vpp_less_mem = vpp_less_mem 

100 if isinstance(swap_os, bool): 

101 self._ctx.swap_os = swap_os 

102 if isinstance(dropless_tok_factor, (int, float)): 

103 self._ctx.dropless_tok_factor = dropless_tok_factor 

104 

105 def __set_node_eval_fun(self, cls_obj, target_node, *args, **kwargs): 

106 """overwrite given node's formulas""" 

107 c_stat, c_dyn = None, None 

108 if (args and args[-1] == 0) or kwargs.get("stat", None) == 0: 

109 c_stat = 0 

110 if (args and args[-1] == 0) or kwargs.get("dyn", None) == 0: 

111 c_dyn = 0 

112 num_p = kwargs.get("num_p", c_stat) 

113 stat_p = kwargs.get("stat_p", c_stat) 

114 stat_os = kwargs.get("stat_os", c_stat) 

115 stat_grad = kwargs.get("stat_grad", c_dyn) 

116 dyn_activ = kwargs.get("dyn_activ", c_dyn) 

117 if not self.__is_valid_eval_func(num_p): 

118 num_p = self._ctx.node_eval[target_node].num_p 

119 if not self.__is_valid_eval_func(stat_p): 

120 stat_p = self._ctx.node_eval[target_node].stat.p 

121 if not self.__is_valid_eval_func(stat_os): 

122 stat_os = self._ctx.node_eval[target_node].stat.os 

123 if not self.__is_valid_eval_func(stat_grad): 

124 stat_grad = self._ctx.node_eval[target_node].stat.grad 

125 if not self.__is_valid_eval_func(dyn_activ): 

126 dyn_activ = self._ctx.node_eval[target_node].dyn.activation 

127 # Compute formulas (FLOPs, not memory — bypass mem_counter) 

128 compute_eval = self.__set_node_eval_compute_fun(target_node, **kwargs) 

129 self._ctx.node_eval[target_node] = NodeEval( 

130 self.__custom_getattr(cls_obj, num_p), 

131 NodeStatEval( 

132 self.__custom_getattr(cls_obj, stat_p, MemType.MODEL_PARAM), 

133 self.__custom_getattr(cls_obj, stat_os, MemType.OPTIM_STATE), 

134 self.__custom_getattr(cls_obj, stat_grad, MemType.ACCU_GRAD), 

135 ), 

136 NodeDynEval( 

137 self.__custom_getattr(cls_obj, dyn_activ), 

138 self.__set_node_eval_comm_fun( 

139 cls_obj, target_node, *args, **kwargs 

140 ), 

141 compute=compute_eval, 

142 ), 

143 ) 

144 

145 def __set_node_eval_comm_fun(self, cls_obj, target_node, *args, **kwargs): 

146 """overwrite given node's comm formulas""" 

147 c_comm = None 

148 positional_zero = args and args[-1] == 0 

149 if positional_zero or kwargs.get("dyn_comm") == 0 or kwargs.get("dyn") == 0: 

150 c_comm = 0 

151 dyn_dp_comm = kwargs.get("dyn_dp_comm", c_comm) 

152 dyn_tp_comm = kwargs.get("dyn_tp_comm", c_comm) 

153 dyn_cp_comm = kwargs.get("dyn_cp_comm", c_comm) 

154 dyn_ep_comm = kwargs.get("dyn_ep_comm", c_comm) 

155 dyn_ep_comm_balanced = kwargs.get("dyn_ep_comm_balanced", None) 

156 dyn_ep_comm_imbalanced = kwargs.get("dyn_ep_comm_imbalanced", None) 

157 if not self.__is_valid_eval_func(dyn_dp_comm): 

158 dyn_dp_comm = self._ctx.node_eval[target_node].dyn.comm.dp 

159 if not self.__is_valid_eval_func(dyn_tp_comm): 

160 dyn_tp_comm = self._ctx.node_eval[target_node].dyn.comm.tp 

161 if not self.__is_valid_eval_func(dyn_cp_comm): 

162 dyn_cp_comm = self._ctx.node_eval[target_node].dyn.comm.cp 

163 if not self.__is_valid_eval_func(dyn_ep_comm): 

164 dyn_ep_comm = self._ctx.node_eval[target_node].dyn.comm.ep 

165 comm_cls_obj = cls_obj 

166 if self.is_regular_layer(target_node): 

167 comm_cls_obj = EvalLayerComm 

168 ep_balanced = ( 

169 self.__custom_getattr(comm_cls_obj, dyn_ep_comm_balanced) 

170 if self.__is_valid_eval_func(dyn_ep_comm_balanced) 

171 else None 

172 ) 

173 ep_imbalanced = ( 

174 self.__custom_getattr(comm_cls_obj, dyn_ep_comm_imbalanced) 

175 if self.__is_valid_eval_func(dyn_ep_comm_imbalanced) 

176 else None 

177 ) 

178 return NodeCommEval( 

179 self.__custom_getattr(comm_cls_obj, dyn_dp_comm), 

180 self.__custom_getattr(comm_cls_obj, dyn_tp_comm), 

181 self.__custom_getattr(comm_cls_obj, dyn_cp_comm), 

182 self.__custom_getattr(comm_cls_obj, dyn_ep_comm), 

183 ep_balanced=ep_balanced, 

184 ep_imbalanced=ep_imbalanced, 

185 ) 

186 

187 def __resolve_compute_fun(self, name): 

188 """Resolve compute formula name — bypasses __wrap_mem_counter. 

189 

190 Compute FLOPs are not memory bytes and must not be accumulated 

191 into accu_mem_type. This method directly retrieves the function 

192 from EvalExpertCompute without the mem_counter wrapper. 

193 Falls back to a zero-returning function if the name is not found, 

194 so YAML typos produce zero FLOPs instead of crashing. 

195 """ 

196 fun = getattr(EvalExpertCompute, name, None) 

197 if fun is not None: 

198 return fun 

199 logger.warning("Compute formula '%s' not found in EvalExpertCompute, " 

200 "falling back to zero", name) 

201 

202 def zero(*_): 

203 return 0 

204 

205 zero.__qualname__ = f"0({name})" 

206 return zero 

207 

208 def __set_node_eval_compute_fun(self, target_node, **kwargs): 

209 """Build NodeComputeEval from kwargs, falling back to existing values.""" 

210 compute_kwargs = kwargs.get("compute", None) 

211 if compute_kwargs is None: 

212 # No compute config provided — preserve existing or return None 

213 existing = self._ctx.node_eval.get(target_node) 

214 if existing and existing.dyn.compute is not None: 

215 return existing.dyn.compute 

216 return None 

217 if not isinstance(compute_kwargs, dict): 

218 return None 

219 router_name = compute_kwargs.get("router", None) 

220 expert_balanced_name = compute_kwargs.get("expert_balanced", None) 

221 expert_imbalanced_name = compute_kwargs.get("expert_imbalanced", None) 

222 shared_expert_name = compute_kwargs.get("shared_expert", None) 

223 # Resolve from EvalExpertCompute (bypass mem_counter) 

224 router = self.__resolve_compute_fun(router_name) if router_name else None 

225 expert_balanced = ( 

226 self.__resolve_compute_fun(expert_balanced_name) 

227 if expert_balanced_name else None 

228 ) 

229 expert_imbalanced = ( 

230 self.__resolve_compute_fun(expert_imbalanced_name) 

231 if expert_imbalanced_name else None 

232 ) 

233 shared_expert = ( 

234 self.__resolve_compute_fun(shared_expert_name) 

235 if shared_expert_name else None 

236 ) 

237 if not any([router, expert_balanced, expert_imbalanced, shared_expert]): 

238 return None 

239 return NodeComputeEval( 

240 router=router, 

241 expert_balanced=expert_balanced, 

242 expert_imbalanced=expert_imbalanced, 

243 shared_expert=shared_expert, 

244 ) 

245 

246 def set_head_eval_fun(self, *arg, **kwarg): 

247 """overwrite head formulas""" 

248 self.__set_node_eval_fun(EvalHead, self._ctx.head_node, *arg, **kwarg) 

249 

250 def set_tail_eval_fun(self, *arg, **kwarg): 

251 """overwrite tail formulas""" 

252 self.__set_node_eval_fun(EvalTail, self._ctx.tail_node, *arg, **kwarg) 

253 

254 def set_body_eval_fun(self, *args, **kwargs): 

255 """overwrite body formulas""" 

256 lay_type = kwargs.get("lay_type", args[0] if args else None) 

257 if not lay_type: 

258 lt = [ 

259 b_obj 

260 for b_obj in list(LayerType) 

261 if self.is_regular_layer(b_obj) 

262 ] 

263 else: 

264 if not isinstance(lay_type, LayerType): 

265 b_obj = self.__custom_getattr(LayerType, lay_type) 

266 lt = [b_obj] 

267 else: 

268 lt = [lay_type] 

269 for b_obj in lt: 

270 self.__set_node_eval_fun(EvalBody, b_obj, *args, **kwargs) 

271 

272 def set_attn_eval_fun( 

273 self, 

274 num_p: Any = None, 

275 qkv: Any = None, 

276 score: Any = None, 

277 proj: Any = None, 

278 ) -> None: 

279 """overwrite attention formulas""" 

280 if self.__is_valid_eval_func(num_p): 

281 self._ctx.attn_num_p = self.__custom_getattr(EvalAttn, num_p) 

282 if self.__is_valid_eval_func(qkv): 

283 self._ctx.attn_qkv_activ = self.__custom_getattr( 

284 EvalAttn, qkv, MemType.ATTN_ACTIV 

285 ) 

286 if self.__is_valid_eval_func(score): 

287 self._ctx.attn_score_activ = self.__custom_getattr( 

288 EvalAttn, score, MemType.ATTN_ACTIV 

289 ) 

290 if self.__is_valid_eval_func(proj): 

291 self._ctx.attn_proj_activ = self.__custom_getattr( 

292 EvalAttn, proj, MemType.ATTN_ACTIV 

293 ) 

294 

295 def set_ffn_eval_fun(self, num_p: Any = None, activation=None, moe_activ=None): 

296 """overwrite feedforward formulas""" 

297 if self.__is_valid_eval_func(num_p): 

298 self._ctx.ffn_num_p = self.__custom_getattr(EvalFFn, num_p) 

299 if self.__is_valid_eval_func(activation): 

300 self._ctx.ffn_activ = self.__custom_getattr( 

301 EvalFFn, activation, MemType.FFN_ACTIV 

302 ) 

303 if self.__is_valid_eval_func(moe_activ): 

304 self._ctx.ffn_moe_activ = self.__custom_getattr( 

305 EvalFFn, moe_activ, MemType.FFN_ACTIV 

306 ) 

307 

308 def set_expert_param_eval_fun( 

309 self, routed_num_p: Any = None, shared_num_p: Any = None, router_num_p: Any = None 

310 ) -> None: 

311 """overwrite expert param count formulas for routed/shared breakdown, and the router's""" 

312 if self.__is_valid_eval_func(routed_num_p): 

313 self._ctx.ffn_routed_num_p = self.__custom_getattr( 

314 EvalFFn, routed_num_p 

315 ) 

316 if self.__is_valid_eval_func(shared_num_p): 

317 self._ctx.ffn_shared_num_p = self.__custom_getattr( 

318 EvalFFn, shared_num_p 

319 ) 

320 if self.__is_valid_eval_func(router_num_p): 

321 self._ctx.ffn_router_num_p = self.__custom_getattr(EvalFFn, router_num_p) 

322 

323 def set_norm_eval_fun(self, num_p: Any = None, activation=None): 

324 """overwrite norm formulas""" 

325 if self.__is_valid_eval_func(num_p): 

326 self._ctx.norm_num_p = self.__custom_getattr(EvalNorm, num_p) 

327 if self.__is_valid_eval_func(activation): 

328 self._ctx.norm_activ = self.__custom_getattr( 

329 EvalNorm, activation, MemType.NORM_ACTIV 

330 ) 

331 

332 def set_pp_micro_factor_eval_fun(self, sched_name, fun): 

333 """overwrite PP microfactor formulas""" 

334 if sched_name and self.__is_valid_eval_func(fun): 

335 self._ctx.pp_micro_eval[sched_name] = self.__custom_getattr( 

336 EvalUtils, fun 

337 ) 

338 

339 # Cost Model Config setter 

340 

341 def set_strategy(self, **kwargs): 

342 """overwrite parallelism""" 

343 self._ccfg.set_strategy(**kwargs) 

344 self.fetch_hook_if_unimodal() 

345 

346 def set_ccfg(self, hook): 

347 """overwrite cost model variable (except strategy)""" 

348 if hook and callable(hook): 

349 with strategy_guarded(self._ccfg): 

350 hook(self._ccfg) 

351 

352 def __wrap_mem_counter(self, mem_type: MemType, fun: Callable) -> None: 

353 """Wrap formula calls to accumulate memory by type.""" 

354 if mem_type and not hasattr(fun, "wrapped_with_counter"): 

355 

356 def wrap(*args, **kwargs): 

357 res = fun(*args, **kwargs) 

358 self._ctx.accu_mem_type[mem_type] += res 

359 self._ctx.save2log(mem_type, res) 

360 return res 

361 

362 wrap.__qualname__ = fun.__qualname__ 

363 wrap.wrapped_with_counter = True 

364 return wrap 

365 return fun 

366 

367 def __custom_getattr( 

368 self, eval_class: Any, field: Any, mem_type: MemType = None 

369 ) -> Callable: 

370 """formula retrieve/wrap""" 

371 # Definition priority order : 

372 # 1. Callable (user defined in code) 

373 # OR Numeric value 

374 # 2. Overriding list from cost_model_preprocess (ccfg attribute) 

375 # 3. Function name (config_eval yaml) 

376 res = None 

377 if callable(field): 

378 res = field 

379 if self.toggle_func_trace == field.__name__: 

380 res = self.func_tracer.wrap(field) 

381 if isinstance(field, (int, float)): 

382 

383 def constant(*_): 

384 return field 

385 

386 constant.__qualname__ = str(field) 

387 res = constant 

388 if field in self._ccfg.overwrite_eval_functions: 

389 res = self._ccfg.overwrite_eval_functions[field] 

390 if isinstance(field, str): 

391 

392 def zero(*_): 

393 return 0 

394 

395 zero.__qualname__ = "0" 

396 res = getattr(eval_class, field, zero) 

397 if self.toggle_func_trace == field: 

398 res = self.func_tracer.wrap(getattr(eval_class, field)) 

399 res = self.__wrap_mem_counter(mem_type, res) 

400 if not res: 

401 raise TypeError(f"In eval config yaml, non valid field: {field}") 

402 return res 

403 

404 # Import Eval Config 

405 

406 def import_eval_yaml(self) -> None: 

407 """import evaluator config file, init ctx (inner call only)""" 

408 if not self.toggle_func_trace: 

409 self.toggle_func_trace = self.eval_cfg.trace_fun 

410 # head 

411 h_obj = getattr(LayerType, self.eval_cfg.nodes_mem_comp.head.name) 

412 self._ctx.head_node = h_obj 

413 self.set_head_eval_fun( 

414 num_p=self.eval_cfg.nodes_mem_comp.head.num_param_fun, 

415 stat_p=self.eval_cfg.nodes_mem_comp.head.stat_fun.p, 

416 stat_os=self.eval_cfg.nodes_mem_comp.head.stat_fun.os, 

417 stat_grad=self.eval_cfg.nodes_mem_comp.head.stat_fun.grad, 

418 dyn_activ=self.eval_cfg.nodes_mem_comp.head.dyn_fun.activation, 

419 dyn_dp_comm=self.eval_cfg.nodes_mem_comp.head.dyn_fun.comm.dp, 

420 dyn_tp_comm=self.eval_cfg.nodes_mem_comp.head.dyn_fun.comm.tp, 

421 dyn_cp_comm=self.eval_cfg.nodes_mem_comp.head.dyn_fun.comm.cp, 

422 dyn_ep_comm=self.eval_cfg.nodes_mem_comp.head.dyn_fun.comm.ep, 

423 ) 

424 

425 # tail 

426 t_obj = getattr(LayerType, self.eval_cfg.nodes_mem_comp.tail.name) 

427 self._ctx.tail_node = t_obj 

428 self.set_tail_eval_fun( 

429 num_p=self.eval_cfg.nodes_mem_comp.tail.num_param_fun, 

430 stat_p=self.eval_cfg.nodes_mem_comp.tail.stat_fun.p, 

431 stat_os=self.eval_cfg.nodes_mem_comp.tail.stat_fun.os, 

432 stat_grad=self.eval_cfg.nodes_mem_comp.tail.stat_fun.grad, 

433 dyn_activ=self.eval_cfg.nodes_mem_comp.tail.dyn_fun.activation, 

434 dyn_dp_comm=self.eval_cfg.nodes_mem_comp.tail.dyn_fun.comm.dp, 

435 dyn_tp_comm=self.eval_cfg.nodes_mem_comp.tail.dyn_fun.comm.tp, 

436 dyn_cp_comm=self.eval_cfg.nodes_mem_comp.tail.dyn_fun.comm.cp, 

437 dyn_ep_comm=self.eval_cfg.nodes_mem_comp.tail.dyn_fun.comm.ep, 

438 ) 

439 

440 # body 

441 for b in self.eval_cfg.nodes_mem_comp.body: 

442 b_cfg = Config(b) 

443 comm_cfg = b_cfg.dyn_fun.comm 

444 comm_kwargs = { 

445 "dyn_dp_comm": comm_cfg.dp, 

446 "dyn_tp_comm": comm_cfg.tp, 

447 "dyn_cp_comm": comm_cfg.cp, 

448 "dyn_ep_comm": comm_cfg.ep, 

449 } 

450 if hasattr(comm_cfg, "ep_balanced"): 

451 comm_kwargs["dyn_ep_comm_balanced"] = comm_cfg.ep_balanced 

452 if hasattr(comm_cfg, "ep_imbalanced"): 

453 comm_kwargs["dyn_ep_comm_imbalanced"] = comm_cfg.ep_imbalanced 

454 # Compute config (FLOPs, not memory) 

455 compute_kwargs = {} 

456 compute_cfg = getattr(b_cfg.dyn_fun, "compute", None) 

457 if compute_cfg and hasattr(compute_cfg, "__dict__"): 

458 compute_kwargs = {"compute": dict(vars(compute_cfg))} 

459 self.set_body_eval_fun( 

460 lay_type=b_cfg.name, 

461 num_p=b_cfg.num_param_fun, 

462 stat_p=b_cfg.stat_fun.p, 

463 stat_os=b_cfg.stat_fun.os, 

464 stat_grad=b_cfg.stat_fun.grad, 

465 dyn_activ=b_cfg.dyn_fun.activation, 

466 **comm_kwargs, 

467 **compute_kwargs, 

468 ) 

469 

470 # pp micro factor 

471 for sc in self.eval_cfg.pp_sched: 

472 self.set_pp_micro_factor_eval_fun(sc["name"], sc["fun"]) 

473 if not self._ccfg.pp_sched: 

474 self._ccfg.pp_sched = self.eval_cfg.default_pp_sched 

475 

476 # layerblock 

477 self.set_attn_eval_fun( 

478 self.eval_cfg.base_arch_mem_comp.attention.num_param_fun, 

479 self.eval_cfg.base_arch_mem_comp.attention.qkv, 

480 self.eval_cfg.base_arch_mem_comp.attention.score, 

481 self.eval_cfg.base_arch_mem_comp.attention.proj, 

482 ) 

483 self.set_ffn_eval_fun( 

484 self.eval_cfg.base_arch_mem_comp.feedforward.num_param_fun, 

485 self.eval_cfg.base_arch_mem_comp.feedforward.activation, 

486 self.eval_cfg.base_arch_mem_comp.feedforward.moe_activ, 

487 ) 

488 self.set_expert_param_eval_fun( 

489 routed_num_p=self.eval_cfg.base_arch_mem_comp.feedforward.routed_num_fun, 

490 shared_num_p=self.eval_cfg.base_arch_mem_comp.feedforward.shared_num_fun, 

491 router_num_p=self.eval_cfg.base_arch_mem_comp.feedforward.router_num_fun, 

492 ) 

493 self.set_norm_eval_fun( 

494 self.eval_cfg.base_arch_mem_comp.norm.num_param_fun, 

495 self.eval_cfg.base_arch_mem_comp.norm.activation, 

496 ) 

497 

498 # passes 

499 self.set_passes( 

500 vpp_less_mem=self.eval_cfg.passes.vpp_less_memory, 

501 swap_os=self.eval_cfg.passes.swap_optimizer, 

502 dropless_tok_factor=self.eval_cfg.passes.dropless_tok_factor, 

503 ) 

504 

505 self._ctx.comm_expr = self.eval_cfg.comm_expr 

506 

507 def is_regular_layer(self, lay): 

508 """check if layer is not head/tail""" 

509 if isinstance(lay, str): 

510 return lay[0] not in [ 

511 self._ctx.head_node.name[0], 

512 self._ctx.tail_node.name[0], 

513 ] 

514 return lay not in [self._ctx.head_node, self._ctx.tail_node]