mplang-nightly 0.1.dev330__tar.gz → 0.1.dev332__tar.gz
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.
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/PKG-INFO +1 -1
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/backends/simp_driver/mem.py +71 -65
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/backends/simp_worker/__init__.py +5 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/backends/simp_worker/comm_context.py +16 -6
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/backends/simp_worker/http.py +35 -35
- mplang_nightly-0.1.dev332/mplang/backends/simp_worker/infra.py +108 -0
- mplang_nightly-0.1.dev332/mplang/backends/simp_worker/request.py +80 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/backends/spu_state.py +70 -20
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/runtime/interpreter.py +63 -178
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/backends/simp_worker/test_comm_context.py +14 -0
- mplang_nightly-0.1.dev332/tests/backends/simp_worker/test_request_isolation.py +182 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/.gitignore +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/LICENSE +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/README.md +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/examples/.gitkeep +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/hatch_build.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/__init__.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/backends/__init__.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/backends/bfv_impl.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/backends/channel.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/backends/crypto_impl.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/backends/field_impl.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/backends/func_impl.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/backends/phe_impl.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/backends/simp_design.md +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/backends/simp_driver/__init__.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/backends/simp_driver/http.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/backends/simp_driver/ops.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/backends/simp_driver/state.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/backends/simp_driver/values.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/backends/simp_worker/base.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/backends/simp_worker/collective_algorithms.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/backends/simp_worker/collectives.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/backends/simp_worker/mem.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/backends/simp_worker/ops.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/backends/simp_worker/state.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/backends/spu_impl.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/backends/store_impl.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/backends/table_impl.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/backends/tee_impl.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/backends/tensor_impl.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/backends/util.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/cli.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/cli_guide.md +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/dialects/__init__.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/dialects/_jax_utils.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/dialects/bfv.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/dialects/crypto.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/dialects/dtypes.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/dialects/field.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/dialects/func.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/dialects/phe.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/dialects/simp.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/dialects/spu.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/dialects/store.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/dialects/table.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/dialects/tee.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/dialects/tensor.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/edsl/README.md +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/edsl/__init__.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/edsl/context.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/edsl/graph.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/edsl/object.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/edsl/primitive.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/edsl/printer.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/edsl/program.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/edsl/registry.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/edsl/serde.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/edsl/tracer.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/edsl/typing.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/extend/__init__.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/extend/arrow/__init__.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/extend/arrow/compute.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/extend/arrow/util.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/extend/arrow/vector.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/kernels/Makefile +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/kernels/__init__.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/kernels/gf128.cpp +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/kernels/ldpc.cpp +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/kernels/okvs.cpp +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/kernels/okvs_opt.cpp +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/kernels/py_kernels.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/libs/collective.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/libs/device/__init__.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/libs/device/api.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/libs/device/cluster.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/libs/ml/__init__.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/libs/ml/sgb.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/libs/mpc/__init__.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/libs/mpc/_utils.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/libs/mpc/analytics/__init__.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/libs/mpc/analytics/aggregation.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/libs/mpc/analytics/groupby.md +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/libs/mpc/analytics/groupby.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/libs/mpc/analytics/permutation.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/libs/mpc/common/constants.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/libs/mpc/ot/__init__.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/libs/mpc/ot/base.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/libs/mpc/ot/extension.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/libs/mpc/ot/silent.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/libs/mpc/psi/__init__.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/libs/mpc/psi/cuckoo.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/libs/mpc/psi/okvs.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/libs/mpc/psi/okvs_gct.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/libs/mpc/psi/oprf.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/libs/mpc/psi/rr22.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/libs/mpc/psi/unbalanced.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/libs/mpc/vole/__init__.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/libs/mpc/vole/gilboa.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/libs/mpc/vole/ldpc.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/libs/mpc/vole/silver.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/py.typed +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/runtime/__init__.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/runtime/dialect_state.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/runtime/object_store.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/runtime/value.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/tool/__init__.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/tool/program.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/utils/__init__.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/utils/func_utils.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/utils/logging.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/pyproject.toml +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/__init__.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/backends/__init__.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/backends/simp_driver/__init__.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/backends/simp_driver/test_http.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/backends/simp_worker/__init__.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/backends/simp_worker/test_async_exec.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/backends/simp_worker/test_base.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/backends/simp_worker/test_collectives.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/backends/simp_worker/test_http.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/backends/simp_worker/test_http_communicator.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/backends/simp_worker/test_mem.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/backends/simp_worker/test_shuffle_exec_id_key.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/backends/test_bfv_impl.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/backends/test_channel.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/backends/test_crypto_impl.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/backends/test_okvs_binding.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/backends/test_simp_integration.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/backends/test_simp_object_store.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/backends/test_spu_impl.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/backends/test_table_impl.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/backends/test_tee_impl.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/backends/test_tensor_impl.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/backends/test_util.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/backends/test_verify_clean.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/conftest.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/dialects/__init__.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/dialects/test_bfv.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/dialects/test_compile_context.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/dialects/test_crypto.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/dialects/test_dtypes.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/dialects/test_field.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/dialects/test_func.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/dialects/test_okvs.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/dialects/test_okvs_bench.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/dialects/test_phe.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/dialects/test_simp.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/dialects/test_simp_comm.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/dialects/test_spu.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/dialects/test_store.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/dialects/test_table.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/dialects/test_table_row_dimension.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/dialects/test_tee.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/dialects/test_tensor.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/edsl/__init__.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/edsl/test_compiled_program_artifact.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/edsl/test_context.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/edsl/test_graph.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/edsl/test_primitive.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/edsl/test_primitive_multi_output.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/edsl/test_printer.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/edsl/test_serde.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/edsl/test_tracer.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/edsl/test_typing.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/edsl/test_typing_graph_serde.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/extend/__init__.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/extend/test_arrow.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/libs/device/__init__.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/libs/device/conftest.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/libs/device/test_device_api_errors.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/libs/device/test_device_dialects.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/libs/device/test_device_layouts.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/libs/device/test_device_tee.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/libs/ml/__init__.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/libs/ml/test_sgb.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/libs/ml/test_sgb_bench.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/libs/mpc/__init__.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/libs/mpc/analytics/__init__.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/libs/mpc/analytics/test_aggregation.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/libs/mpc/analytics/test_groupby.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/libs/mpc/analytics/test_permutation.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/libs/mpc/ot/__init__.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/libs/mpc/ot/test_ot.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/libs/mpc/ot/test_ot_extension.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/libs/mpc/ot/test_silent_ot.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/libs/mpc/psi/__init__.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/libs/mpc/psi/test_okvs_gct.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/libs/mpc/psi/test_oprf.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/libs/mpc/psi/test_psi.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/libs/mpc/psi/test_psi_bench.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/libs/mpc/psi/test_rr22.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/libs/mpc/psi/verify_psi_okvs_logic.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/libs/mpc/test_field_gf128.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/libs/mpc/test_utils.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/libs/mpc/vole/__init__.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/libs/mpc/vole/test_gilboa_manual.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/libs/mpc/vole/test_ldpc.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/libs/mpc/vole/test_silver_vole.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/libs/mpc/vole/test_vole.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/libs/mpc/vole/test_vole_bench.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/libs/mpc/vole/verify_vole_logic.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/libs/test_collective.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/libs/test_simple_guide.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/runtime/test_interpreter_async.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/runtime/test_object_store.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/runtime/test_object_store_fs.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/runtime/test_value_gc.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/test_fetch_semantics.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/test_pytree_io.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/utils/__init__.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/utils/tensor_patch.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/utils/test_func_utils.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tests/utils/test_logging.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tutorials/00_device_basics.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tutorials/01_function_decorator.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tutorials/02_simulation_and_driver.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tutorials/03_run_jax.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tutorials/04_ir_dump_and_analysis.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tutorials/05_run_sql.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tutorials/06_pipeline.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tutorials/07_stax_nn.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tutorials/08_logging.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tutorials/MIGRATION.md +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tutorials/README.md +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tutorials/__init__.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tutorials/data/alice.csv +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tutorials/data/bob.csv +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tutorials/data/prepare_vertical_iris.py +0 -0
- {mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/tutorials/run.sh +0 -0
|
@@ -23,9 +23,10 @@ from collections.abc import Callable
|
|
|
23
23
|
from typing import TYPE_CHECKING, Any, cast
|
|
24
24
|
|
|
25
25
|
from mplang.backends.simp_driver.state import SimpDriver
|
|
26
|
-
from mplang.backends.simp_worker import WORKER_HANDLERS
|
|
27
|
-
from mplang.backends.simp_worker.
|
|
26
|
+
from mplang.backends.simp_worker import WORKER_HANDLERS
|
|
27
|
+
from mplang.backends.simp_worker.infra import DEFAULT_ASYNC_OPS, WorkerInfra
|
|
28
28
|
from mplang.backends.simp_worker.mem import LocalMesh
|
|
29
|
+
from mplang.backends.simp_worker.request import create_request_interpreter
|
|
29
30
|
from mplang.runtime.interpreter import ExecutionTracer, Interpreter
|
|
30
31
|
from mplang.runtime.object_store import FileSystemBackend, ObjectStore
|
|
31
32
|
|
|
@@ -37,10 +38,14 @@ if TYPE_CHECKING:
|
|
|
37
38
|
|
|
38
39
|
|
|
39
40
|
class MemCluster:
|
|
40
|
-
"""Orchestrator that creates and manages local worker
|
|
41
|
+
"""Orchestrator that creates and manages local worker infrastructure.
|
|
41
42
|
|
|
42
43
|
This class handles worker lifecycle management. It does NOT attach to
|
|
43
44
|
an Interpreter - instead, it creates a SimpMemDriver that can be attached.
|
|
45
|
+
|
|
46
|
+
Per-request Interpreters are created on-the-fly by ``create_request_interpreter``
|
|
47
|
+
to isolate mutable state (CommContext, SimpWorker, SPUState) across concurrent
|
|
48
|
+
requests.
|
|
44
49
|
"""
|
|
45
50
|
|
|
46
51
|
def __init__(
|
|
@@ -75,8 +80,9 @@ class MemCluster:
|
|
|
75
80
|
)
|
|
76
81
|
self.tracer.start()
|
|
77
82
|
|
|
78
|
-
# Create
|
|
79
|
-
self.
|
|
83
|
+
# Create shared WorkerInfra per rank (replaces per-rank Interpreters)
|
|
84
|
+
self._infras: list[WorkerInfra] = []
|
|
85
|
+
self._stores: list[ObjectStore] = []
|
|
80
86
|
for rank in range(world_size):
|
|
81
87
|
worker_root = cluster_root / f"node{rank}"
|
|
82
88
|
store = ObjectStore(
|
|
@@ -84,60 +90,50 @@ class MemCluster:
|
|
|
84
90
|
root_path=str(worker_root / "store"),
|
|
85
91
|
)
|
|
86
92
|
)
|
|
93
|
+
self._stores.append(store)
|
|
87
94
|
|
|
88
|
-
|
|
95
|
+
w_handlers: dict[str, Callable[..., Any]] = {**WORKER_HANDLERS} # type: ignore[dict-item]
|
|
96
|
+
infra = WorkerInfra(
|
|
89
97
|
rank=rank,
|
|
90
98
|
world_size=world_size,
|
|
91
99
|
communicator=self._mesh.comms[rank],
|
|
92
100
|
store=store,
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
w_handlers: dict[str, Callable[..., Any]] = {**WORKER_HANDLERS} # type: ignore[dict-item]
|
|
96
|
-
comm_ctx = CommContext(
|
|
97
|
-
self._mesh.comms[rank],
|
|
98
|
-
context_id="ctx",
|
|
99
|
-
my_rank=rank,
|
|
100
|
-
)
|
|
101
|
-
w_interp = Interpreter(
|
|
102
|
-
name=f"Worker-{rank}",
|
|
101
|
+
handlers=w_handlers,
|
|
103
102
|
tracer=self.tracer,
|
|
104
103
|
trace_pid=rank,
|
|
105
|
-
store=store,
|
|
106
104
|
root_dir=worker_root,
|
|
107
|
-
|
|
108
|
-
|
|
105
|
+
# async_ops has no effect when executor is None (MemCluster
|
|
106
|
+
# runs each request synchronously on the mesh executor thread).
|
|
107
|
+
# We still set it so that WorkerInfra carries the canonical set
|
|
108
|
+
# for introspection and consistency with the HTTP Worker path.
|
|
109
|
+
async_ops=DEFAULT_ASYNC_OPS,
|
|
109
110
|
)
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
w_interp.async_ops = {
|
|
113
|
-
"bfv.add",
|
|
114
|
-
"bfv.mul",
|
|
115
|
-
"bfv.rotate",
|
|
116
|
-
"bfv.batch_encode",
|
|
117
|
-
"bfv.relinearize",
|
|
118
|
-
"bfv.encrypt",
|
|
119
|
-
"bfv.decrypt",
|
|
120
|
-
"field.solve_okvs",
|
|
121
|
-
"field.decode_okvs",
|
|
122
|
-
"field.aes_expand",
|
|
123
|
-
"field.mul",
|
|
124
|
-
"simp.shuffle",
|
|
125
|
-
}
|
|
126
|
-
self._workers.append(w_interp)
|
|
111
|
+
self._infras.append(infra)
|
|
127
112
|
|
|
128
113
|
@property
|
|
129
114
|
def world_size(self) -> int:
|
|
130
115
|
return self._world_size
|
|
131
116
|
|
|
132
117
|
@property
|
|
133
|
-
def
|
|
134
|
-
return self.
|
|
118
|
+
def infras(self) -> list[WorkerInfra]:
|
|
119
|
+
return self._infras
|
|
120
|
+
|
|
121
|
+
@property
|
|
122
|
+
def workers(self) -> list[WorkerInfra]:
|
|
123
|
+
"""Backward-compatible alias for ``infras``.
|
|
124
|
+
|
|
125
|
+
.. note:: Returns ``WorkerInfra`` objects (not ``Interpreter``). Only
|
|
126
|
+
the ``.store`` attribute is guaranteed by this interface. Callers
|
|
127
|
+
needing full Interpreter access should use
|
|
128
|
+
``create_request_interpreter(infra, job_id)`` instead.
|
|
129
|
+
"""
|
|
130
|
+
return self._infras
|
|
135
131
|
|
|
136
132
|
def create_state(self) -> SimpMemDriver:
|
|
137
133
|
"""Create a SimpMemDriver that can be attached to a Driver Interpreter."""
|
|
138
134
|
return SimpMemDriver(
|
|
139
135
|
world_size=self._world_size,
|
|
140
|
-
|
|
136
|
+
infras=self._infras,
|
|
141
137
|
mesh=self._mesh,
|
|
142
138
|
)
|
|
143
139
|
|
|
@@ -158,11 +154,11 @@ class SimpMemDriver(SimpDriver):
|
|
|
158
154
|
def __init__(
|
|
159
155
|
self,
|
|
160
156
|
world_size: int,
|
|
161
|
-
|
|
157
|
+
infras: list[WorkerInfra],
|
|
162
158
|
mesh: Any, # LocalMesh from simp_worker.mem
|
|
163
159
|
) -> None:
|
|
164
160
|
self._world_size = world_size
|
|
165
|
-
self.
|
|
161
|
+
self._infras = infras
|
|
166
162
|
self._mesh = mesh
|
|
167
163
|
|
|
168
164
|
def shutdown(self) -> None:
|
|
@@ -174,9 +170,18 @@ class SimpMemDriver(SimpDriver):
|
|
|
174
170
|
return self._world_size
|
|
175
171
|
|
|
176
172
|
@property
|
|
177
|
-
def
|
|
178
|
-
"""Worker
|
|
179
|
-
return self.
|
|
173
|
+
def infras(self) -> list[WorkerInfra]:
|
|
174
|
+
"""Worker infrastructure (shared, immutable)."""
|
|
175
|
+
return self._infras
|
|
176
|
+
|
|
177
|
+
@property
|
|
178
|
+
def workers(self) -> list[WorkerInfra]:
|
|
179
|
+
"""Backward-compatible alias for ``infras``.
|
|
180
|
+
|
|
181
|
+
.. note:: Returns ``WorkerInfra`` objects (not ``Interpreter``). Only
|
|
182
|
+
the ``.store`` attribute is guaranteed by this interface.
|
|
183
|
+
"""
|
|
184
|
+
return self._infras
|
|
180
185
|
|
|
181
186
|
def submit(
|
|
182
187
|
self, rank: int, graph: Graph, inputs: list[Any], job_id: str | None = None
|
|
@@ -205,31 +210,32 @@ class SimpMemDriver(SimpDriver):
|
|
|
205
210
|
|
|
206
211
|
def fetch(self, rank: int, uri: str) -> Future[Any]:
|
|
207
212
|
"""Fetch directly from worker store."""
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
return self._mesh.executor.submit(lambda: worker_ctx.store.get(uri)) # type: ignore[no-any-return]
|
|
213
|
+
infra = self._infras[rank]
|
|
214
|
+
return self._mesh.executor.submit(lambda: infra.store.get(uri)) # type: ignore[no-any-return]
|
|
211
215
|
|
|
212
216
|
def _run_worker(
|
|
213
217
|
self, rank: int, graph: Graph, inputs: list[Any], job_id: str | None = None
|
|
214
218
|
) -> Any:
|
|
215
|
-
"""Execute on
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
219
|
+
"""Execute on a per-request Interpreter."""
|
|
220
|
+
infra = self._infras[rank]
|
|
221
|
+
request_interp = create_request_interpreter(infra, job_id or "anonymous")
|
|
222
|
+
try:
|
|
223
|
+
# Resolve URI inputs (None means rank has no data)
|
|
224
|
+
resolved_inputs = [
|
|
225
|
+
infra.store.get(inp) if inp is not None else None for inp in inputs
|
|
226
|
+
]
|
|
227
|
+
|
|
228
|
+
# Execute
|
|
229
|
+
results = request_interp.evaluate_graph(graph, resolved_inputs, job_id)
|
|
230
|
+
|
|
231
|
+
# Store results (results is always a list)
|
|
232
|
+
if not graph.outputs:
|
|
233
|
+
return None
|
|
234
|
+
return [
|
|
235
|
+
infra.store.put(res) if res is not None else None for res in results
|
|
236
|
+
]
|
|
237
|
+
finally:
|
|
238
|
+
request_interp.shutdown()
|
|
233
239
|
|
|
234
240
|
|
|
235
241
|
def make_simulator(
|
{mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/backends/simp_worker/__init__.py
RENAMED
|
@@ -38,11 +38,14 @@ from mplang.backends.simp_worker.http import (
|
|
|
38
38
|
RecvTimeoutError,
|
|
39
39
|
SendTimeoutError,
|
|
40
40
|
)
|
|
41
|
+
from mplang.backends.simp_worker.infra import DEFAULT_ASYNC_OPS, WorkerInfra
|
|
41
42
|
from mplang.backends.simp_worker.mem import LocalMesh, ThreadCommunicator
|
|
42
43
|
from mplang.backends.simp_worker.ops import WORKER_HANDLERS
|
|
44
|
+
from mplang.backends.simp_worker.request import create_request_interpreter
|
|
43
45
|
from mplang.backends.simp_worker.state import SimpWorker
|
|
44
46
|
|
|
45
47
|
__all__ = [
|
|
48
|
+
"DEFAULT_ASYNC_OPS",
|
|
46
49
|
"WORKER_HANDLERS",
|
|
47
50
|
"CommConfig",
|
|
48
51
|
"CommStats",
|
|
@@ -56,6 +59,8 @@ __all__ = [
|
|
|
56
59
|
"SendTimeoutError",
|
|
57
60
|
"SimpWorker",
|
|
58
61
|
"ThreadCommunicator",
|
|
62
|
+
"WorkerInfra",
|
|
63
|
+
"create_request_interpreter",
|
|
59
64
|
"testall",
|
|
60
65
|
"testany",
|
|
61
66
|
"wait_all",
|
{mplang_nightly-0.1.dev330 → mplang_nightly-0.1.dev332}/mplang/backends/simp_worker/comm_context.py
RENAMED
|
@@ -62,15 +62,25 @@ class CommContext:
|
|
|
62
62
|
def world_size(self) -> int:
|
|
63
63
|
return self._comm.world_size
|
|
64
64
|
|
|
65
|
-
def spawn(self) -> CommContext:
|
|
65
|
+
def spawn(self, suffix: str | None = None) -> CommContext:
|
|
66
66
|
"""Create a child context with independent counter namespace.
|
|
67
67
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
68
|
+
Args:
|
|
69
|
+
suffix: Explicit suffix for the child context ID. When provided,
|
|
70
|
+
``context_id = f"{parent_id}.{suffix}"``. This is used when
|
|
71
|
+
the caller needs a deterministic, content-based ID that is
|
|
72
|
+
stable across ranks regardless of call order (e.g. the async
|
|
73
|
+
DAG scheduler uses ``f"{graph_exec_key}.{op_idx}"``).
|
|
74
|
+
|
|
75
|
+
When *None* (default), an auto-incrementing counter is used:
|
|
76
|
+
``context_id = f"{parent_id}.{spawn_seq}"``. This is suitable
|
|
77
|
+
for SPMD code where all ranks call ``spawn()`` in the same
|
|
78
|
+
program-order position.
|
|
72
79
|
"""
|
|
73
|
-
|
|
80
|
+
if suffix is None:
|
|
81
|
+
child_id = f"{self._id}.{self._spawn_counter}"
|
|
82
|
+
else:
|
|
83
|
+
child_id = f"{self._id}.{self._spawn_counter}.{suffix}"
|
|
74
84
|
self._spawn_counter += 1
|
|
75
85
|
return CommContext(self._comm, child_id, self._rank)
|
|
76
86
|
|
|
@@ -61,10 +61,10 @@ from mplang.backends.simp_worker.base import (
|
|
|
61
61
|
wait_all,
|
|
62
62
|
wait_any,
|
|
63
63
|
)
|
|
64
|
-
from mplang.backends.simp_worker.
|
|
64
|
+
from mplang.backends.simp_worker.infra import WorkerInfra
|
|
65
65
|
from mplang.edsl import serde
|
|
66
66
|
from mplang.edsl.graph import Graph
|
|
67
|
-
from mplang.runtime.interpreter import ExecutionTracer
|
|
67
|
+
from mplang.runtime.interpreter import ExecutionTracer
|
|
68
68
|
from mplang.runtime.object_store import FileSystemBackend, ObjectStore
|
|
69
69
|
from mplang.utils.logging import get_logger
|
|
70
70
|
|
|
@@ -636,7 +636,7 @@ def register_routes(
|
|
|
636
636
|
*,
|
|
637
637
|
rank: int,
|
|
638
638
|
world_size: int,
|
|
639
|
-
|
|
639
|
+
infra: WorkerInfra,
|
|
640
640
|
comm: HttpCommunicator,
|
|
641
641
|
store: ObjectStore,
|
|
642
642
|
exec_pool: concurrent.futures.ThreadPoolExecutor,
|
|
@@ -648,36 +648,38 @@ def register_routes(
|
|
|
648
648
|
enabling reuse in custom server setups.
|
|
649
649
|
|
|
650
650
|
Note:
|
|
651
|
-
The *
|
|
652
|
-
|
|
653
|
-
any request is served, as the ``/fetch`` and ``/objects`` endpoints
|
|
654
|
-
rely on it.
|
|
651
|
+
The *infra* ``WorkerInfra`` contains all shared infrastructure needed
|
|
652
|
+
to create per-request Interpreters.
|
|
655
653
|
|
|
656
654
|
Args:
|
|
657
655
|
app: The FastAPI application to register routes on.
|
|
658
656
|
rank: This worker's rank.
|
|
659
657
|
world_size: Total number of workers.
|
|
660
|
-
|
|
658
|
+
infra: The WorkerInfra for creating per-request Interpreters.
|
|
661
659
|
comm: The HttpCommunicator for inter-worker communication.
|
|
662
660
|
store: The ObjectStore for data persistence.
|
|
663
661
|
exec_pool: Thread pool for executing graphs.
|
|
664
662
|
"""
|
|
665
|
-
from
|
|
663
|
+
from mplang.backends.simp_worker.request import create_request_interpreter
|
|
666
664
|
|
|
667
665
|
def _do_execute(graph: Graph, inputs: list[Any], job_id: str | None = None) -> Any:
|
|
668
|
-
"""Execute graph in worker thread."""
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
666
|
+
"""Execute graph in worker thread with per-request isolation."""
|
|
667
|
+
request_interp = create_request_interpreter(infra, job_id or "anonymous")
|
|
668
|
+
try:
|
|
669
|
+
# Resolve URI inputs (None means rank has no data)
|
|
670
|
+
resolved_inputs = [
|
|
671
|
+
store.get(inp) if inp is not None else None for inp in inputs
|
|
672
|
+
]
|
|
673
673
|
|
|
674
|
-
|
|
675
|
-
|
|
674
|
+
result = request_interp.evaluate_graph(graph, resolved_inputs, job_id)
|
|
675
|
+
comm.wait_pending_sends()
|
|
676
676
|
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
677
|
+
# Store results and return URIs (result is always a list)
|
|
678
|
+
if not graph.outputs:
|
|
679
|
+
return None
|
|
680
|
+
return [store.put(res) if res is not None else None for res in result]
|
|
681
|
+
finally:
|
|
682
|
+
request_interp.shutdown()
|
|
681
683
|
|
|
682
684
|
# Mutable closure state shared between endpoint handlers and exec_pool threads.
|
|
683
685
|
async_tasks: dict[str, AsyncTaskState] = {}
|
|
@@ -845,8 +847,7 @@ def register_routes(
|
|
|
845
847
|
"""Fetch data by URI (e.g. ``mem://abc123``, ``fs://ckpt/s100``)."""
|
|
846
848
|
logger.debug(f"Worker {rank} received fetch request for {req.uri}")
|
|
847
849
|
try:
|
|
848
|
-
|
|
849
|
-
val = state.store.get(req.uri)
|
|
850
|
+
val = store.get(req.uri)
|
|
850
851
|
return {"result": serde.dumps_b64(val)}
|
|
851
852
|
except Exception as e:
|
|
852
853
|
logger.error(f"Worker {rank} fetch failed: {e}")
|
|
@@ -856,8 +857,7 @@ def register_routes(
|
|
|
856
857
|
def list_objects() -> dict[str, list[str]]:
|
|
857
858
|
"""List all objects in the worker's store (transient + persistent)."""
|
|
858
859
|
try:
|
|
859
|
-
|
|
860
|
-
return {"objects": state.store.list_keys()}
|
|
860
|
+
return {"objects": store.list_keys()}
|
|
861
861
|
except Exception as e:
|
|
862
862
|
logger.error(f"Worker {rank} list_objects failed: {e}")
|
|
863
863
|
raise HTTPException(status_code=500, detail=str(e)) from e
|
|
@@ -917,22 +917,22 @@ def create_worker_app(
|
|
|
917
917
|
comm = HttpCommunicator(rank, world_size, endpoints, tracer=tracer)
|
|
918
918
|
if store is None:
|
|
919
919
|
store = ObjectStore(persistent=FileSystemBackend(root_path=str(root_dir)))
|
|
920
|
-
ctx = SimpWorker(rank, world_size, comm, store, spu_endpoints)
|
|
921
920
|
|
|
922
921
|
handlers: dict[str, Callable[..., Any]] = {**WORKER_HANDLERS} # type: ignore[dict-item]
|
|
923
922
|
|
|
924
|
-
from mplang.backends.simp_worker.
|
|
923
|
+
from mplang.backends.simp_worker.infra import DEFAULT_ASYNC_OPS, WorkerInfra
|
|
925
924
|
|
|
926
|
-
|
|
927
|
-
|
|
925
|
+
infra = WorkerInfra(
|
|
926
|
+
rank=rank,
|
|
927
|
+
world_size=world_size,
|
|
928
|
+
communicator=comm,
|
|
929
|
+
store=store,
|
|
930
|
+
handlers=handlers,
|
|
931
|
+
spu_endpoints=spu_endpoints,
|
|
928
932
|
tracer=tracer,
|
|
929
933
|
root_dir=root_dir,
|
|
930
|
-
|
|
931
|
-
store=store,
|
|
932
|
-
comm_ctx=comm_ctx,
|
|
934
|
+
async_ops=DEFAULT_ASYNC_OPS,
|
|
933
935
|
)
|
|
934
|
-
# Register SimpWorker context as 'simp' dialect state
|
|
935
|
-
worker.set_dialect_state("simp", ctx)
|
|
936
936
|
|
|
937
937
|
exec_pool = concurrent.futures.ThreadPoolExecutor(
|
|
938
938
|
max_workers=2, thread_name_prefix=f"exec_{rank}"
|
|
@@ -941,7 +941,7 @@ def create_worker_app(
|
|
|
941
941
|
@asynccontextmanager
|
|
942
942
|
async def lifespan(app: FastAPI) -> AsyncIterator[None]:
|
|
943
943
|
yield
|
|
944
|
-
await asyncio.to_thread(
|
|
944
|
+
await asyncio.to_thread(infra.shutdown)
|
|
945
945
|
await asyncio.to_thread(comm.shutdown)
|
|
946
946
|
await asyncio.to_thread(exec_pool.shutdown, wait=True)
|
|
947
947
|
|
|
@@ -951,7 +951,7 @@ def create_worker_app(
|
|
|
951
951
|
app,
|
|
952
952
|
rank=rank,
|
|
953
953
|
world_size=world_size,
|
|
954
|
-
|
|
954
|
+
infra=infra,
|
|
955
955
|
comm=comm,
|
|
956
956
|
store=store,
|
|
957
957
|
exec_pool=exec_pool,
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# Copyright 2026 Ant Group 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
|
+
"""WorkerInfra: shared infrastructure container for per-request Interpreter creation.
|
|
16
|
+
|
|
17
|
+
Created once at Worker startup. Passed to ``create_request_interpreter()`` for
|
|
18
|
+
each incoming request. All fields are either immutable or thread-safe.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
from __future__ import annotations
|
|
22
|
+
|
|
23
|
+
import concurrent.futures
|
|
24
|
+
import pathlib
|
|
25
|
+
import threading
|
|
26
|
+
from collections.abc import Callable
|
|
27
|
+
from dataclasses import dataclass, field
|
|
28
|
+
from typing import Any
|
|
29
|
+
|
|
30
|
+
from mplang.backends.simp_worker.base import CommunicatorProtocol
|
|
31
|
+
from mplang.runtime.interpreter import ExecutionTracer
|
|
32
|
+
from mplang.runtime.object_store import ObjectStore
|
|
33
|
+
|
|
34
|
+
# Opcodes eligible for async DAG scheduling when an Executor is present.
|
|
35
|
+
# Kept as a module-level constant so that both MemCluster and HTTP Worker
|
|
36
|
+
# share the same set without duplication.
|
|
37
|
+
DEFAULT_ASYNC_OPS: frozenset[str] = frozenset({
|
|
38
|
+
"bfv.add",
|
|
39
|
+
"bfv.mul",
|
|
40
|
+
"bfv.rotate",
|
|
41
|
+
"bfv.batch_encode",
|
|
42
|
+
"bfv.relinearize",
|
|
43
|
+
"bfv.encrypt",
|
|
44
|
+
"bfv.decrypt",
|
|
45
|
+
"field.solve_okvs",
|
|
46
|
+
"field.decode_okvs",
|
|
47
|
+
"field.aes_expand",
|
|
48
|
+
"field.mul",
|
|
49
|
+
"simp.shuffle",
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
@dataclass
|
|
54
|
+
class WorkerInfra:
|
|
55
|
+
"""Shared infrastructure for a Worker process.
|
|
56
|
+
|
|
57
|
+
Created once at Worker startup. Passed to each per-request Interpreter
|
|
58
|
+
factory. All fields are either immutable or thread-safe.
|
|
59
|
+
"""
|
|
60
|
+
|
|
61
|
+
rank: int
|
|
62
|
+
world_size: int
|
|
63
|
+
communicator: CommunicatorProtocol
|
|
64
|
+
store: ObjectStore
|
|
65
|
+
handlers: dict[str, Callable[..., Any]]
|
|
66
|
+
spu_endpoints: dict[int, str] | None = None
|
|
67
|
+
tracer: ExecutionTracer | None = None
|
|
68
|
+
trace_pid: int | None = None
|
|
69
|
+
root_dir: pathlib.Path | None = None
|
|
70
|
+
executor: concurrent.futures.Executor | None = None
|
|
71
|
+
async_ops: frozenset[str] = field(default_factory=frozenset)
|
|
72
|
+
|
|
73
|
+
# SPU template links (lazily populated, protected by lock).
|
|
74
|
+
# Cache keys are (local_rank, spu_world_size, protocol, field, link_mode).
|
|
75
|
+
# The number of distinct keys is bounded by the Cartesian product of SPU
|
|
76
|
+
# configurations actually used at runtime -- typically 1-3 entries per
|
|
77
|
+
# worker process (one per distinct SPU device declaration).
|
|
78
|
+
_spu_lock: threading.Lock = field(default_factory=threading.Lock, repr=False)
|
|
79
|
+
_spu_template_links: dict[tuple, Any] = field(default_factory=dict, repr=False)
|
|
80
|
+
|
|
81
|
+
def get_or_create_spu_link(
|
|
82
|
+
self,
|
|
83
|
+
cache_key: tuple,
|
|
84
|
+
create_fn: Callable[[], Any],
|
|
85
|
+
) -> Any:
|
|
86
|
+
"""Thread-safe lazy creation of template SPU links.
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
cache_key: Tuple identifying the SPU configuration.
|
|
90
|
+
create_fn: Factory function to create a new link context.
|
|
91
|
+
|
|
92
|
+
Returns:
|
|
93
|
+
A libspu.link.Context (template link) for the given configuration.
|
|
94
|
+
"""
|
|
95
|
+
with self._spu_lock:
|
|
96
|
+
if cache_key not in self._spu_template_links:
|
|
97
|
+
self._spu_template_links[cache_key] = create_fn()
|
|
98
|
+
return self._spu_template_links[cache_key]
|
|
99
|
+
|
|
100
|
+
def shutdown(self) -> None:
|
|
101
|
+
"""Release cached SPU template links.
|
|
102
|
+
|
|
103
|
+
Safe to call multiple times. Should be called during process
|
|
104
|
+
shutdown to eagerly close BRPC connections rather than waiting
|
|
105
|
+
for GC / process exit.
|
|
106
|
+
"""
|
|
107
|
+
with self._spu_lock:
|
|
108
|
+
self._spu_template_links.clear()
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# Copyright 2026 Ant Group 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
|
+
"""Per-request Interpreter factory.
|
|
16
|
+
|
|
17
|
+
Creates lightweight Interpreter instances for each incoming request,
|
|
18
|
+
providing full isolation of mutable state (CommContext, SimpWorker,
|
|
19
|
+
SPUState) while sharing immutable infrastructure (Communicator, Store,
|
|
20
|
+
handlers).
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
from __future__ import annotations
|
|
24
|
+
|
|
25
|
+
from mplang.backends.simp_worker.comm_context import CommContext
|
|
26
|
+
from mplang.backends.simp_worker.infra import WorkerInfra
|
|
27
|
+
from mplang.backends.simp_worker.state import SimpWorker
|
|
28
|
+
from mplang.backends.spu_state import SPUState
|
|
29
|
+
from mplang.runtime.interpreter import Interpreter
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def create_request_interpreter(
|
|
33
|
+
infra: WorkerInfra,
|
|
34
|
+
job_id: str,
|
|
35
|
+
) -> Interpreter:
|
|
36
|
+
"""Create a lightweight Interpreter for a single request.
|
|
37
|
+
|
|
38
|
+
Cost: ~2μs (dict/TLS allocation only).
|
|
39
|
+
SPU Runtime created on-demand via link.spawn() (~120μs).
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
infra: Shared WorkerInfra (process-lifetime).
|
|
43
|
+
job_id: Unique request identifier (used as CommContext context_id).
|
|
44
|
+
|
|
45
|
+
Returns:
|
|
46
|
+
Per-request Interpreter with isolated state.
|
|
47
|
+
"""
|
|
48
|
+
# Per-request CommContext with unique context_id
|
|
49
|
+
comm_ctx = CommContext(infra.communicator, context_id=job_id, my_rank=infra.rank)
|
|
50
|
+
|
|
51
|
+
# Per-request Interpreter (does not own shared executor/tracer)
|
|
52
|
+
interp = Interpreter(
|
|
53
|
+
name=f"Worker-{infra.rank}-{job_id}",
|
|
54
|
+
tracer=infra.tracer,
|
|
55
|
+
trace_pid=infra.trace_pid,
|
|
56
|
+
store=infra.store,
|
|
57
|
+
root_dir=infra.root_dir,
|
|
58
|
+
handlers=infra.handlers,
|
|
59
|
+
executor=infra.executor,
|
|
60
|
+
comm_ctx=comm_ctx,
|
|
61
|
+
owns_executor=False,
|
|
62
|
+
owns_tracer=False,
|
|
63
|
+
)
|
|
64
|
+
interp.async_ops = set(infra.async_ops)
|
|
65
|
+
|
|
66
|
+
# Per-request SimpWorker: isolates current_parties
|
|
67
|
+
worker_state = SimpWorker(
|
|
68
|
+
rank=infra.rank,
|
|
69
|
+
world_size=infra.world_size,
|
|
70
|
+
communicator=infra.communicator, # raw comm kept for SPU BaseChannel
|
|
71
|
+
store=infra.store,
|
|
72
|
+
spu_endpoints=infra.spu_endpoints,
|
|
73
|
+
)
|
|
74
|
+
interp.set_dialect_state("simp", worker_state)
|
|
75
|
+
|
|
76
|
+
# Per-request SPUState: will use link.spawn() for Runtime isolation
|
|
77
|
+
spu_state = SPUState(infra=infra)
|
|
78
|
+
interp.set_dialect_state("spu", spu_state)
|
|
79
|
+
|
|
80
|
+
return interp
|