@@ -1272,6 +1272,58 @@ def path_c_fused_in_region_parameter_bank_aliases(
12721272 break
12731273 return out
12741274
1275+ def _path_c_static_real_abi_input_values (
1276+ self ,
1277+ abi_map : Mapping [str , Any ],
1278+ ) -> dict [str , mx .array ]:
1279+ """Return small non-trainable real-ABI inputs required by Path C.
1280+
1281+ The fused train-block ABI contains a few real inputs that are neither
1282+ trainable parameters nor per-batch runtime tensors. For Sparse-MLA
1283+ these are the softmax scale and optional attention sinks. They must be
1284+ written into model-owned banks along with parameter values; leaving the
1285+ zero-initialized bank slots in place makes the forward/backward kernel
1286+ run with ``sm_scale=0`` and kills q/kv gradients.
1287+ """
1288+
1289+ attention = self .config .attention_config ("dsa" )
1290+ sm_scale = float (attention .q_head_dim ) ** - 0.5
1291+ values : dict [str , mx .array ] = {}
1292+ for logical_name , info in abi_map .items ():
1293+ if not isinstance (info , Mapping ):
1294+ continue
1295+ shape = tuple (
1296+ int (dim )
1297+ for dim in tuple (info .get ("logical_shape" , info .get ("shape" , ())))
1298+ )
1299+ if str (logical_name ).endswith ("sparse_mla_sm_scale" ):
1300+ values [str (logical_name )] = mx .array (
1301+ [sm_scale ], dtype = mx .float32
1302+ ).reshape (shape or (1 ,))
1303+ elif str (logical_name ).endswith ("sparse_mla_sinks" ):
1304+ values [str (logical_name )] = mx .zeros (shape , dtype = mx .float32 )
1305+ elif str (logical_name ).endswith ("sparse_mla_has_sinks" ):
1306+ values [str (logical_name )] = mx .zeros (shape , dtype = mx .int32 )
1307+ return values
1308+
1309+ def _sync_path_c_static_real_abi_inputs_into_bank (
1310+ self ,
1311+ * ,
1312+ abi_map : Mapping [str , Any ],
1313+ buffers : Mapping [str , Any ],
1314+ ) -> tuple [list [str ], list [tuple [str , str ]]]:
1315+ synced : list [str ] = []
1316+ skipped : list [tuple [str , str ]] = []
1317+ for logical_name , value in sorted (
1318+ self ._path_c_static_real_abi_input_values (abi_map ).items ()
1319+ ):
1320+ try :
1321+ write_into_bank_slot (abi_map , buffers , logical_name , value )
1322+ synced .append (logical_name )
1323+ except Exception as exc :
1324+ skipped .append ((logical_name , f"{ type (exc ).__name__ } : { exc } " ))
1325+ return synced , skipped
1326+
12751327 def _path_c_lookup_parameter_holder (
12761328 self ,
12771329 parameter_name : str ,
@@ -1378,6 +1430,13 @@ def sync_path_c_in_region_parameters_into_bank(
13781430 )
13791431 synced : list [str ] = []
13801432 skipped : list [tuple [str , str ]] = []
1433+ static_synced , static_skipped = (
1434+ self ._sync_path_c_static_real_abi_inputs_into_bank (
1435+ abi_map = abi_map ,
1436+ buffers = buffers ,
1437+ )
1438+ )
1439+ skipped .extend (static_skipped )
13811440 for parameter_name , info in sorted (aliases .items ()):
13821441 tensor = self ._path_c_get_parameter_tensor (parameter_name )
13831442 if tensor is None :
@@ -1414,6 +1473,11 @@ def sync_path_c_in_region_parameters_into_bank(
14141473 {"parameter_name" : name , "reason" : reason }
14151474 for name , reason in skipped
14161475 ],
1476+ "static_real_abi_inputs_synced" : static_synced ,
1477+ "static_real_abi_inputs_skipped" : [
1478+ {"logical_name" : name , "reason" : reason }
1479+ for name , reason in static_skipped
1480+ ],
14171481 }
14181482
14191483 def bind_path_c_in_region_parameter_views_into_bank (
@@ -1486,6 +1550,13 @@ def bind_path_c_in_region_parameter_views_into_bank(
14861550 )
14871551 bound : list [str ] = []
14881552 skipped : list [tuple [str , str ]] = []
1553+ static_synced , static_skipped = (
1554+ self ._sync_path_c_static_real_abi_inputs_into_bank (
1555+ abi_map = abi_map ,
1556+ buffers = buffers ,
1557+ )
1558+ )
1559+ skipped .extend (static_skipped )
14891560 for parameter_name , info in sorted (aliases .items ()):
14901561 tensor = self ._path_c_get_parameter_tensor (parameter_name )
14911562 if tensor is None :
@@ -1524,6 +1595,11 @@ def bind_path_c_in_region_parameter_views_into_bank(
15241595 "in_region_parameter_count" : len (bound ),
15251596 "in_region_parameter_names" : tuple (sorted (bound )),
15261597 "in_region_parameter_bank_aliases" : dict (aliases ),
1598+ "static_real_abi_inputs_synced" : static_synced ,
1599+ "static_real_abi_inputs_skipped" : [
1600+ {"logical_name" : name , "reason" : reason }
1601+ for name , reason in static_skipped
1602+ ],
15271603 }
15281604
15291605 def path_c_fused_first_in_region_layer_index (
0 commit comments