VBoussot commited on
Commit
d2b63cb
·
1 Parent(s): 86c3da0

fix(convexadam): disable only the TensorExpr fuser during registration

Browse files

The TS feature models trip torch's TensorExpr fuser alias analysis (INTERNAL ASSERT on aten::size/dim in FuseTensorExprs) when itk-impact runs them. Verified via itk-impact: model-side is impossible (itk-impact passes an undefined direction, so guarding it needs a shape op = the fuser trigger); disabling the fuser is the only fix. Scope it (_no_texpr_fuser) to the registration: modern profiling executor stays on (not legacy), measured ~1% cost (fuser only touches the few feature forwards, not the 150-iter C++ optimisation loop).

ConvexAdam_Coarse/Model.py CHANGED
@@ -33,6 +33,7 @@ NOTE: do NOT add ``from __future__ import annotations`` — KonfAI's config engi
33
  runtime-evaluated annotations (``get_origin``); PEP 563 stringized annotations break binding.
34
  """
35
 
 
36
  import json
37
  import os
38
  from dataclasses import dataclass, field
@@ -106,6 +107,22 @@ class ModelSpec:
106
  distance: Literal["L1", "L2", "Dice", "Cosine", "NCC"] = "L1"
107
 
108
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
109
  def _coarse_registration_type():
110
  """The coupled-convex initializer, tolerant to the two names the wrapping has shipped under."""
111
  cls = getattr(itk, "ImpactCoarseRegistration", None) or getattr(itk, "ImpactConvexAdamInitializer", None)
@@ -444,7 +461,7 @@ class ConvexAdamRegistration(torch.nn.Module):
444
  # ConvexAdam runs a gradient-based instance optimisation (Adam over the field) inside itk-impact's
445
  # .Update(); the predictor calls forward under torch.inference_mode(), which forbids autograd. The
446
  # image tensors have already crossed to numpy/ITK here, so re-enable grad for the optimisation.
447
- with torch.inference_mode(False), torch.enable_grad():
448
  for b in range(fixed.shape[0]):
449
  fixed_img = data_to_image(fixed[b].detach().cpu().numpy(), fixed_attrs[b])
450
  moving_img = data_to_image(moving[b].detach().cpu().numpy(), moving_attrs[b])
 
33
  runtime-evaluated annotations (``get_origin``); PEP 563 stringized annotations break binding.
34
  """
35
 
36
+ import contextlib
37
  import json
38
  import os
39
  from dataclasses import dataclass, field
 
107
  distance: Literal["L1", "L2", "Dice", "Cosine", "NCC"] = "L1"
108
 
109
 
110
+ @contextlib.contextmanager
111
+ def _no_texpr_fuser():
112
+ """Disable ONLY torch's TensorExpr (NNC) fuser for the block. The TS feature-model graphs have a direction/
113
+ orientation branch whose shape ops (aten::dim / aten::size) crash the fuser's alias analysis under itk-impact
114
+ ("INTERNAL ASSERT ... We don't have an op for aten::size" in FuseTensorExprs). It cannot be fixed model-side:
115
+ itk-impact passes an *undefined* direction, so guarding it needs a shape op — the very fuser trigger. The
116
+ modern profiling executor stays on (NOT the legacy executor); measured cost ~1% of a registration (the fuser
117
+ only touches the few feature forwards, not the C++ optimisation loop). The caller's setting is restored."""
118
+ prev = torch._C._jit_texpr_fuser_enabled()
119
+ torch._C._jit_set_texpr_fuser_enabled(False)
120
+ try:
121
+ yield
122
+ finally:
123
+ torch._C._jit_set_texpr_fuser_enabled(prev)
124
+
125
+
126
  def _coarse_registration_type():
127
  """The coupled-convex initializer, tolerant to the two names the wrapping has shipped under."""
128
  cls = getattr(itk, "ImpactCoarseRegistration", None) or getattr(itk, "ImpactConvexAdamInitializer", None)
 
461
  # ConvexAdam runs a gradient-based instance optimisation (Adam over the field) inside itk-impact's
462
  # .Update(); the predictor calls forward under torch.inference_mode(), which forbids autograd. The
463
  # image tensors have already crossed to numpy/ITK here, so re-enable grad for the optimisation.
464
+ with torch.inference_mode(False), torch.enable_grad(), _no_texpr_fuser():
465
  for b in range(fixed.shape[0]):
466
  fixed_img = data_to_image(fixed[b].detach().cpu().numpy(), fixed_attrs[b])
467
  moving_img = data_to_image(moving[b].detach().cpu().numpy(), moving_attrs[b])
ConvexAdam_Composite/Model.py CHANGED
@@ -33,6 +33,7 @@ NOTE: do NOT add ``from __future__ import annotations`` — KonfAI's config engi
33
  runtime-evaluated annotations (``get_origin``); PEP 563 stringized annotations break binding.
34
  """
35
 
 
36
  import json
37
  import os
38
  from dataclasses import dataclass, field
@@ -106,6 +107,22 @@ class ModelSpec:
106
  distance: Literal["L1", "L2", "Dice", "Cosine", "NCC"] = "L1"
107
 
108
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
109
  def _coarse_registration_type():
110
  """The coupled-convex initializer, tolerant to the two names the wrapping has shipped under."""
111
  cls = getattr(itk, "ImpactCoarseRegistration", None) or getattr(itk, "ImpactConvexAdamInitializer", None)
@@ -444,7 +461,7 @@ class ConvexAdamRegistration(torch.nn.Module):
444
  # ConvexAdam runs a gradient-based instance optimisation (Adam over the field) inside itk-impact's
445
  # .Update(); the predictor calls forward under torch.inference_mode(), which forbids autograd. The
446
  # image tensors have already crossed to numpy/ITK here, so re-enable grad for the optimisation.
447
- with torch.inference_mode(False), torch.enable_grad():
448
  for b in range(fixed.shape[0]):
449
  fixed_img = data_to_image(fixed[b].detach().cpu().numpy(), fixed_attrs[b])
450
  moving_img = data_to_image(moving[b].detach().cpu().numpy(), moving_attrs[b])
 
33
  runtime-evaluated annotations (``get_origin``); PEP 563 stringized annotations break binding.
34
  """
35
 
36
+ import contextlib
37
  import json
38
  import os
39
  from dataclasses import dataclass, field
 
107
  distance: Literal["L1", "L2", "Dice", "Cosine", "NCC"] = "L1"
108
 
109
 
110
+ @contextlib.contextmanager
111
+ def _no_texpr_fuser():
112
+ """Disable ONLY torch's TensorExpr (NNC) fuser for the block. The TS feature-model graphs have a direction/
113
+ orientation branch whose shape ops (aten::dim / aten::size) crash the fuser's alias analysis under itk-impact
114
+ ("INTERNAL ASSERT ... We don't have an op for aten::size" in FuseTensorExprs). It cannot be fixed model-side:
115
+ itk-impact passes an *undefined* direction, so guarding it needs a shape op — the very fuser trigger. The
116
+ modern profiling executor stays on (NOT the legacy executor); measured cost ~1% of a registration (the fuser
117
+ only touches the few feature forwards, not the C++ optimisation loop). The caller's setting is restored."""
118
+ prev = torch._C._jit_texpr_fuser_enabled()
119
+ torch._C._jit_set_texpr_fuser_enabled(False)
120
+ try:
121
+ yield
122
+ finally:
123
+ torch._C._jit_set_texpr_fuser_enabled(prev)
124
+
125
+
126
  def _coarse_registration_type():
127
  """The coupled-convex initializer, tolerant to the two names the wrapping has shipped under."""
128
  cls = getattr(itk, "ImpactCoarseRegistration", None) or getattr(itk, "ImpactConvexAdamInitializer", None)
 
461
  # ConvexAdam runs a gradient-based instance optimisation (Adam over the field) inside itk-impact's
462
  # .Update(); the predictor calls forward under torch.inference_mode(), which forbids autograd. The
463
  # image tensors have already crossed to numpy/ITK here, so re-enable grad for the optimisation.
464
+ with torch.inference_mode(False), torch.enable_grad(), _no_texpr_fuser():
465
  for b in range(fixed.shape[0]):
466
  fixed_img = data_to_image(fixed[b].detach().cpu().numpy(), fixed_attrs[b])
467
  moving_img = data_to_image(moving[b].detach().cpu().numpy(), moving_attrs[b])
ConvexAdam_Fine/Model.py CHANGED
@@ -33,6 +33,7 @@ NOTE: do NOT add ``from __future__ import annotations`` — KonfAI's config engi
33
  runtime-evaluated annotations (``get_origin``); PEP 563 stringized annotations break binding.
34
  """
35
 
 
36
  import json
37
  import os
38
  from dataclasses import dataclass, field
@@ -106,6 +107,22 @@ class ModelSpec:
106
  distance: Literal["L1", "L2", "Dice", "Cosine", "NCC"] = "L1"
107
 
108
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
109
  def _coarse_registration_type():
110
  """The coupled-convex initializer, tolerant to the two names the wrapping has shipped under."""
111
  cls = getattr(itk, "ImpactCoarseRegistration", None) or getattr(itk, "ImpactConvexAdamInitializer", None)
@@ -444,7 +461,7 @@ class ConvexAdamRegistration(torch.nn.Module):
444
  # ConvexAdam runs a gradient-based instance optimisation (Adam over the field) inside itk-impact's
445
  # .Update(); the predictor calls forward under torch.inference_mode(), which forbids autograd. The
446
  # image tensors have already crossed to numpy/ITK here, so re-enable grad for the optimisation.
447
- with torch.inference_mode(False), torch.enable_grad():
448
  for b in range(fixed.shape[0]):
449
  fixed_img = data_to_image(fixed[b].detach().cpu().numpy(), fixed_attrs[b])
450
  moving_img = data_to_image(moving[b].detach().cpu().numpy(), moving_attrs[b])
 
33
  runtime-evaluated annotations (``get_origin``); PEP 563 stringized annotations break binding.
34
  """
35
 
36
+ import contextlib
37
  import json
38
  import os
39
  from dataclasses import dataclass, field
 
107
  distance: Literal["L1", "L2", "Dice", "Cosine", "NCC"] = "L1"
108
 
109
 
110
+ @contextlib.contextmanager
111
+ def _no_texpr_fuser():
112
+ """Disable ONLY torch's TensorExpr (NNC) fuser for the block. The TS feature-model graphs have a direction/
113
+ orientation branch whose shape ops (aten::dim / aten::size) crash the fuser's alias analysis under itk-impact
114
+ ("INTERNAL ASSERT ... We don't have an op for aten::size" in FuseTensorExprs). It cannot be fixed model-side:
115
+ itk-impact passes an *undefined* direction, so guarding it needs a shape op — the very fuser trigger. The
116
+ modern profiling executor stays on (NOT the legacy executor); measured cost ~1% of a registration (the fuser
117
+ only touches the few feature forwards, not the C++ optimisation loop). The caller's setting is restored."""
118
+ prev = torch._C._jit_texpr_fuser_enabled()
119
+ torch._C._jit_set_texpr_fuser_enabled(False)
120
+ try:
121
+ yield
122
+ finally:
123
+ torch._C._jit_set_texpr_fuser_enabled(prev)
124
+
125
+
126
  def _coarse_registration_type():
127
  """The coupled-convex initializer, tolerant to the two names the wrapping has shipped under."""
128
  cls = getattr(itk, "ImpactCoarseRegistration", None) or getattr(itk, "ImpactConvexAdamInitializer", None)
 
461
  # ConvexAdam runs a gradient-based instance optimisation (Adam over the field) inside itk-impact's
462
  # .Update(); the predictor calls forward under torch.inference_mode(), which forbids autograd. The
463
  # image tensors have already crossed to numpy/ITK here, so re-enable grad for the optimisation.
464
+ with torch.inference_mode(False), torch.enable_grad(), _no_texpr_fuser():
465
  for b in range(fixed.shape[0]):
466
  fixed_img = data_to_image(fixed[b].detach().cpu().numpy(), fixed_attrs[b])
467
  moving_img = data_to_image(moving[b].detach().cpu().numpy(), moving_attrs[b])
ConvexAdam_Fine/__pycache__/Model.cpython-313.pyc CHANGED
Binary files a/ConvexAdam_Fine/__pycache__/Model.cpython-313.pyc and b/ConvexAdam_Fine/__pycache__/Model.cpython-313.pyc differ