mplang-nightly 0.1.dev332__py3-none-any.whl → 0.1.dev334__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -45,8 +45,8 @@ def _wrap_op_as_graph(op: Operation) -> Graph:
45
45
  # Create graph inputs
46
46
  graph_inputs = [g.add_input(f"in_{i}", any_type) for i in range(len(op.inputs))]
47
47
 
48
- # Determine output types
49
- output_types = [out.type for out in op.outputs] if op.outputs else [any_type]
48
+ # Determine output types (faithfully mirror the original op)
49
+ output_types = [out.type for out in op.outputs]
50
50
 
51
51
  # Add the operation (this handles outputs and value registration)
52
52
  g.add_op(
@@ -77,7 +77,7 @@ def _collect_to_hostvars(results: list[Any], num_outputs: int, world_size: int)
77
77
  Single DriverVar if num_outputs == 1, else list of DriverVars
78
78
  """
79
79
  if num_outputs == 0:
80
- return None
80
+ return []
81
81
 
82
82
  # Transpose [worker][output] -> [output][worker]
83
83
  # results[worker_idx] is a list of URIs for that worker's outputs
@@ -117,7 +117,7 @@ def _generic_simp_dispatch(interpreter: Any, op: Operation, *args: Any) -> Any:
117
117
  results = driver.collect(futures)
118
118
 
119
119
  # 4. Assemble into DriverVar(s)
120
- num_outputs = len(op.outputs) if op.outputs else 1
120
+ num_outputs = len(op.outputs)
121
121
  return _collect_to_hostvars(results, num_outputs, world_size)
122
122
 
123
123
 
@@ -53,13 +53,19 @@ def _pcall_static_worker_impl(
53
53
 
54
54
  try:
55
55
  result = interpreter.evaluate_graph(fn_graph, list(args))
56
- # Return single value for single output (interpreter expects this)
57
- return result[0] if len(op.outputs) == 1 else result
56
+ # Use inner graph's actual output count for safety
57
+ n_out = len(fn_graph.outputs)
58
+ if n_out == 0:
59
+ return []
60
+ return result[0] if n_out == 1 else result
58
61
  finally:
59
62
  worker.current_parties = prev_parties
60
63
  else:
61
64
  # No data for this rank
62
- return None if len(op.outputs) == 1 else [None] * len(op.outputs)
65
+ n_out = len(op.outputs)
66
+ if n_out == 0:
67
+ return []
68
+ return None if n_out == 1 else [None] * n_out
63
69
 
64
70
 
65
71
  def _pcall_dynamic_worker_impl(
@@ -68,7 +74,10 @@ def _pcall_dynamic_worker_impl(
68
74
  """Worker implementation of pcall_dynamic."""
69
75
  fn_graph = op.regions[0]
70
76
  result = interpreter.evaluate_graph(fn_graph, list(args))
71
- return result[0] if len(op.outputs) == 1 else result
77
+ n_out = len(fn_graph.outputs)
78
+ if n_out == 0:
79
+ return []
80
+ return result[0] if n_out == 1 else result
72
81
 
73
82
 
74
83
  def _shuffle_static_worker_impl(
@@ -20,6 +20,9 @@ multiple executions while binding to the Interpreter's lifecycle.
20
20
 
21
21
  from __future__ import annotations
22
22
 
23
+ import logging
24
+ import os
25
+ from dataclasses import dataclass, field
23
26
  from typing import TYPE_CHECKING, Any
24
27
 
25
28
  import spu.api as spu_api
@@ -31,6 +34,64 @@ if TYPE_CHECKING:
31
34
  from mplang.backends.simp_worker.infra import WorkerInfra
32
35
  from mplang.dialects import spu
33
36
 
37
+ logger = logging.getLogger(__name__)
38
+
39
+
40
+ def _opt_int_env(name: str) -> int | None:
41
+ """Read an optional int env var; return None when unset/empty."""
42
+ val = os.getenv(name)
43
+ return int(val) if val else None
44
+
45
+
46
+ @dataclass(frozen=True)
47
+ class BrpcLinkConfig:
48
+ """Tunables for the brpc-backed SPU link.
49
+
50
+ Defaults come from environment variables so deployments can switch
51
+ protocol/timeouts without code changes; explicit constructor args
52
+ still win for tests and programmatic overrides.
53
+
54
+ Set ``protocol`` to ``"http"`` (HTTP/1.1) or ``"h2"`` (HTTP/2) when
55
+ traffic must traverse an L7 gateway that does not understand the
56
+ default ``baidu_std`` binary protocol. HTTP/1.1 requires
57
+ ``connection_type="pooled"`` to avoid head-of-line blocking.
58
+
59
+ ``http_timeout_ms`` defaults to ``None`` (use brpc's own default) —
60
+ long-running MPC jobs traversing a gateway with idle timeout should
61
+ set this explicitly to cover the longest single RPC.
62
+
63
+ Frozen so instances are hashable and safe to embed in cache keys.
64
+ """
65
+
66
+ protocol: str = field(
67
+ default_factory=lambda: os.getenv("MPLANG_BRPC_PROTOCOL") or "http"
68
+ )
69
+ connection_type: str = field(
70
+ default_factory=lambda: os.getenv("MPLANG_BRPC_CONN_TYPE") or "pooled"
71
+ )
72
+ recv_timeout_ms: int = field(
73
+ default_factory=lambda: int(os.getenv("MPLANG_BRPC_RECV_TIMEOUT_MS") or 100000)
74
+ )
75
+ http_max_payload_size: int = field(
76
+ default_factory=lambda: int(
77
+ os.getenv("MPLANG_BRPC_HTTP_MAX_PAYLOAD") or 32 * 1024 * 1024
78
+ )
79
+ )
80
+ # Per-RPC HTTP timeout. None = inherit brpc default. Set when going
81
+ # through a gateway with its own idle/request timeout.
82
+ http_timeout_ms: int | None = field(
83
+ default_factory=lambda: _opt_int_env("MPLANG_BRPC_HTTP_TIMEOUT_MS")
84
+ )
85
+ # Initial connect retry — tolerates peers that come up later.
86
+ connect_retry_times: int = field(
87
+ default_factory=lambda: int(os.getenv("MPLANG_BRPC_CONNECT_RETRY_TIMES") or 60)
88
+ )
89
+ connect_retry_interval_ms: int = field(
90
+ default_factory=lambda: int(
91
+ os.getenv("MPLANG_BRPC_CONNECT_RETRY_INTERVAL_MS") or 1000
92
+ )
93
+ )
94
+
34
95
 
35
96
  class SPUState(DialectState):
36
97
  """SPU Runtime cache as dialect state.
@@ -48,13 +109,22 @@ class SPUState(DialectState):
48
109
 
49
110
  dialect_name: str = "spu"
50
111
 
51
- def __init__(self, infra: WorkerInfra | None = None) -> None:
112
+ def __init__(
113
+ self,
114
+ infra: WorkerInfra | None = None,
115
+ brpc_config: BrpcLinkConfig | None = None,
116
+ ) -> None:
52
117
  # Optional shared infrastructure (for per-request isolation via link.spawn)
53
118
  self._infra = infra
54
- # Key: (local_rank, world_size, protocol, field, link_mode, spu_endpoints)
119
+ self._brpc_config = brpc_config or BrpcLinkConfig()
120
+ # Key: (local_rank, world_size, protocol, field, link_mode, spu_endpoints, brpc_config)
121
+ # ``brpc_config`` participates only when link_mode == "brpc" (else None) so that
122
+ # callers passing custom configs don't silently reuse the first config's link.
55
123
  # Value: (Runtime, Io)
56
124
  self._runtimes: dict[
57
- tuple[int, int, str, str, str, tuple[str, ...] | None],
125
+ tuple[
126
+ int, int, str, str, str, tuple[str, ...] | None, BrpcLinkConfig | None
127
+ ],
58
128
  tuple[spu_api.Runtime, spu_api.Io],
59
129
  ] = {}
60
130
  # Local template link cache (used when no WorkerInfra is provided)
@@ -140,6 +210,7 @@ class SPUState(DialectState):
140
210
  config.field,
141
211
  link_mode,
142
212
  tuple(spu_endpoints) if spu_endpoints else None,
213
+ self._brpc_config if link_mode == "brpc" else None,
143
214
  )
144
215
 
145
216
  if cache_key in self._runtimes:
@@ -222,13 +293,36 @@ class SPUState(DialectState):
222
293
  self, local_rank: int, spu_endpoints: list[str]
223
294
  ) -> libspu.link.Context:
224
295
  """Create BRPC link for distributed execution."""
296
+ cfg = self._brpc_config
225
297
  desc = libspu.link.Desc() # type: ignore
226
- desc.recv_timeout_ms = 100 * 1000 # 100 seconds
227
- desc.http_max_payload_size = 32 * 1024 * 1024 # 32MB
298
+ desc.recv_timeout_ms = cfg.recv_timeout_ms
299
+ desc.http_max_payload_size = cfg.http_max_payload_size
300
+ desc.brpc_channel_protocol = cfg.protocol
301
+ desc.brpc_channel_connection_type = cfg.connection_type
302
+ desc.connect_retry_times = cfg.connect_retry_times
303
+ desc.connect_retry_interval_ms = cfg.connect_retry_interval_ms
304
+ if cfg.http_timeout_ms is not None:
305
+ desc.http_timeout_ms = cfg.http_timeout_ms
228
306
 
229
307
  for i, endpoint in enumerate(spu_endpoints):
230
308
  desc.add_party(f"P{i}", endpoint)
231
309
 
310
+ logger.info(
311
+ "Creating SPU brpc link: rank=%d, endpoints=%s, protocol=%s, "
312
+ "connection_type=%s, recv_timeout_ms=%d, http_timeout_ms=%s, "
313
+ "http_max_payload_size=%d, connect_retry_times=%d, "
314
+ "connect_retry_interval_ms=%d",
315
+ local_rank,
316
+ spu_endpoints,
317
+ cfg.protocol,
318
+ cfg.connection_type,
319
+ cfg.recv_timeout_ms,
320
+ cfg.http_timeout_ms,
321
+ cfg.http_max_payload_size,
322
+ cfg.connect_retry_times,
323
+ cfg.connect_retry_interval_ms,
324
+ )
325
+
232
326
  return libspu.link.create_brpc(desc, local_rank)
233
327
 
234
328
  def shutdown(self) -> None:
@@ -1082,7 +1082,9 @@ class Interpreter(AbstractInterpreter):
1082
1082
  return
1083
1083
 
1084
1084
  # Store results
1085
- if len(op.outputs) == 1:
1085
+ if len(op.outputs) == 0:
1086
+ pass # Void operation
1087
+ elif len(op.outputs) == 1:
1086
1088
  env[op.outputs[0]] = result
1087
1089
  else:
1088
1090
  for out_val, res in zip(op.outputs, result, strict=True):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mplang-nightly
3
- Version: 0.1.dev332
3
+ Version: 0.1.dev334
4
4
  Summary: Multi-Party Programming Language
5
5
  Author-email: SecretFlow Team <secretflow-contact@service.alipay.com>
6
6
  License: Apache License
@@ -11,7 +11,7 @@ mplang/backends/func_impl.py,sha256=vhkSJnvgSzvQWXqOE40O8npqOmtNqLxefzv9ETuQODQ,
11
11
  mplang/backends/phe_impl.py,sha256=CefRpFrRJvbZm3X58OYOFAyNZXKDp081Q6CT8fhdreE,4118
12
12
  mplang/backends/simp_design.md,sha256=u4YeDLKk5avsueXhzPtt4OUBToBmurOVK_BWTKTJ7w0,5246
13
13
  mplang/backends/spu_impl.py,sha256=73JTdIFqWoKgVM5jR1lJm_PODlgb9BrQUwLSDcGWi20,11876
14
- mplang/backends/spu_state.py,sha256=XKquhcAND8afEUzzfJ3VFb1wQ3ptFuPptStxHt20JpA,8652
14
+ mplang/backends/spu_state.py,sha256=GaCAPRrTpr6YDz-6eHXW8jpHaSpPr79fPnvT09x0Xbw,12315
15
15
  mplang/backends/store_impl.py,sha256=IeoMxt9Ma21aYv-dKgF7COinvO6uc09aw5gGTp-5Ctg,1599
16
16
  mplang/backends/table_impl.py,sha256=g3fjXOdHUoEEE1w330C5n5FwKcM26cQSo0jPgxNQFsE,30104
17
17
  mplang/backends/tee_impl.py,sha256=5yed94Lr55hgSDT6j3FjdTboqzhl4HpJ9lGk1YGZBXQ,7026
@@ -20,7 +20,7 @@ mplang/backends/util.py,sha256=yrftyGCxOHSfyTawopGhrErUrfgV_5xXqHgEjEY3f8A,3940
20
20
  mplang/backends/simp_driver/__init__.py,sha256=pQkHGR8HagnPB4OqagPZY-Ul19y6HjIJ5dY6QXZrBH8,1243
21
21
  mplang/backends/simp_driver/http.py,sha256=cPcX2f2SIXy6NtQDjSaCJGr8qKut-WcOSmAP2UQomrk,5674
22
22
  mplang/backends/simp_driver/mem.py,sha256=sb4TT61VEOf384PoMK2WAOCI0SN_iH03bVLo0e7DLBU,10213
23
- mplang/backends/simp_driver/ops.py,sha256=WYObWDRCsiXH0UBWZX5vD5W98ZPkd88U_qBV8SE5rA8,4503
23
+ mplang/backends/simp_driver/ops.py,sha256=pf980pEvKLhsAgvbxNLvK8FEgKA-OF3XaqSYK7yocRo,4486
24
24
  mplang/backends/simp_driver/state.py,sha256=dNmYMFN2D2BBdgs6C0YLaHrfaBRMgs05UNxMWw6tZIs,1713
25
25
  mplang/backends/simp_driver/values.py,sha256=Lz1utNSIzH-dCzZAEjU6JRcxPsfKGfUJrYl6gIuMOGw,1509
26
26
  mplang/backends/simp_worker/__init__.py,sha256=MGfnuvkP6mh9FzSOpLCZ96bgqDydE8GNYCtBhidPiWk,1922
@@ -31,7 +31,7 @@ mplang/backends/simp_worker/comm_context.py,sha256=EmDNYOpCP5p8nCL1nJcj9Ztua8Kb_
31
31
  mplang/backends/simp_worker/http.py,sha256=7SEnQE8a-vbNTQEd4xIo2jhI8AsaEqsYZ8IcINsg8qY,35129
32
32
  mplang/backends/simp_worker/infra.py,sha256=9f-MpuNbL3vUdkOwGg8EW6ZJPyA41JJTTnTqhvtD4A8,3848
33
33
  mplang/backends/simp_worker/mem.py,sha256=2AWTvv1awtGt-GaEpfnGLE9QoeaCCdfz1BgEKklVorA,6171
34
- mplang/backends/simp_worker/ops.py,sha256=SlZ9bJGkvoTwgXjvWvyrNsinf3B-zMm04XVL8IEKYMs,5628
34
+ mplang/backends/simp_worker/ops.py,sha256=nL83HXTjzrLMX8UFRllxErtBQw4qZonte1Z8Gv8A0Xw,5815
35
35
  mplang/backends/simp_worker/request.py,sha256=J_qPh0Crj8DWvrEEzAMt7ie-F4AvEl_1AaYlfWf3TtQ,2771
36
36
  mplang/backends/simp_worker/state.py,sha256=nIu0ybvdYqRqp0TkoSneUF2u31evDHucCRduVBaDals,1445
37
37
  mplang/dialects/__init__.py,sha256=CYMmkeQVU0Znr9n3_5clZKb16u7acJ5jl5Zjbx4Tn1U,1478
@@ -103,7 +103,7 @@ mplang/libs/mpc/vole/ldpc.py,sha256=gOmIbyOjkGE5lewyatl3p6FizNNH8LZ_1oOhp_-TOck,
103
103
  mplang/libs/mpc/vole/silver.py,sha256=EIxhpFIVNBemgeIZzCu5Cz_4wysxRm9b1Xfu0xiweVQ,12218
104
104
  mplang/runtime/__init__.py,sha256=VdUwJ3kDaI46FvGw7iMGwcsjt0HTGmmRmaBwj99xKIw,620
105
105
  mplang/runtime/dialect_state.py,sha256=HxO1i4kSOujS2tQzAF9-WmI3nChSaGgupf2_07dHetY,1277
106
- mplang/runtime/interpreter.py,sha256=boz3LDziXJbgYBDCVG_NwsXD9jGteHYHqn3lksTBVGs,46199
106
+ mplang/runtime/interpreter.py,sha256=lUuNC3_LQq-KHHbZWfpErLBCtjRFdpZlUmBg5zX4u9Y,46285
107
107
  mplang/runtime/object_store.py,sha256=8Xqr87mkKuQIs-gVZ89Nk62o2GjJDk8meQ4TT66i4aQ,17916
108
108
  mplang/runtime/value.py,sha256=EqlhSgxLTJi_FF3ppyKjMe4eHS6-ROx-zK1YesG1U4o,4311
109
109
  mplang/tool/__init__.py,sha256=9K-T50W_vClUlyERcVx5xGZaeyv0Ts63SaQX6AZtjIs,1341
@@ -111,8 +111,8 @@ mplang/tool/program.py,sha256=W3H8bpPirnoJ4ZrmyPYuMCPadJis20o__n_1MKqCsWU,11058
111
111
  mplang/utils/__init__.py,sha256=Hwrwti2nfPxWUXV8DN6T1QaqXH_Jsd27k8UMSdBGUns,1073
112
112
  mplang/utils/func_utils.py,sha256=Jdn_60jN3jcSE_oAqSMTLQjiE8CLyPpY-H1HmPIL5mw,5354
113
113
  mplang/utils/logging.py,sha256=9dMhwprVbx1WMGJrgoQbWmV50vyYuLU4NSPnetcl1Go,7237
114
- mplang_nightly-0.1.dev332.dist-info/METADATA,sha256=H4LyHhbLgPXLlYVKdf1sNzDai9gAqU_JMw20NA92NEo,16783
115
- mplang_nightly-0.1.dev332.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
116
- mplang_nightly-0.1.dev332.dist-info/entry_points.txt,sha256=mG1oJT-GAjQR834a62_QIWb7litzWPPyVnwFqm-rWuY,55
117
- mplang_nightly-0.1.dev332.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
118
- mplang_nightly-0.1.dev332.dist-info/RECORD,,
114
+ mplang_nightly-0.1.dev334.dist-info/METADATA,sha256=1Ll8lb24EHRGprpryfOwceq8pLUY-5Gd3ZQGykJqhxs,16783
115
+ mplang_nightly-0.1.dev334.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
116
+ mplang_nightly-0.1.dev334.dist-info/entry_points.txt,sha256=mG1oJT-GAjQR834a62_QIWb7litzWPPyVnwFqm-rWuY,55
117
+ mplang_nightly-0.1.dev334.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
118
+ mplang_nightly-0.1.dev334.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: hatchling 1.29.0
2
+ Generator: hatchling 1.30.1
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any