blazefl 2.0.0.dev1__tar.gz → 2.0.0.dev3__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.
Files changed (115) hide show
  1. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/Makefile +1 -1
  2. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/PKG-INFO +1 -1
  3. blazefl-2.0.0.dev3/examples/experimental-freethreaded/.python-version +1 -0
  4. blazefl-2.0.0.dev3/examples/experimental-freethreaded/Makefile +6 -0
  5. blazefl-2.0.0.dev3/examples/experimental-freethreaded/config/config.yaml +17 -0
  6. blazefl-2.0.0.dev3/examples/experimental-freethreaded/main.py +219 -0
  7. blazefl-2.0.0.dev3/examples/experimental-freethreaded/pyproject.toml +37 -0
  8. blazefl-2.0.0.dev3/examples/experimental-freethreaded/uv.lock +569 -0
  9. blazefl-2.0.0.dev3/examples/quickstart-fedavg/dataset/__init__.py +3 -0
  10. blazefl-2.0.0.dev3/examples/quickstart-fedavg/dataset/dataset.py +133 -0
  11. blazefl-2.0.0.dev3/examples/quickstart-fedavg/dataset/functional.py +136 -0
  12. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/examples/quickstart-fedavg/main.py +9 -9
  13. blazefl-2.0.0.dev3/examples/quickstart-fedavg/models/__init__.py +3 -0
  14. blazefl-2.0.0.dev3/examples/quickstart-fedavg/models/selector.py +45 -0
  15. blazefl-2.0.0.dev3/examples/step-by-step-dsfl/.gitignore +3 -0
  16. blazefl-2.0.0.dev3/examples/step-by-step-dsfl/algorithm/__init__.py +3 -0
  17. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/examples/step-by-step-dsfl/algorithm/dsfl.py +11 -11
  18. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/examples/step-by-step-dsfl/main.py +5 -5
  19. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/pyproject.toml +1 -1
  20. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/src/blazefl/contrib/__init__.py +6 -6
  21. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/src/blazefl/contrib/fedavg.py +15 -13
  22. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/src/blazefl/core/__init__.py +10 -5
  23. blazefl-2.0.0.dev3/src/blazefl/core/__init__.pyi +6 -0
  24. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/src/blazefl/core/client_trainer.py +45 -12
  25. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/src/blazefl/core/client_trainer.pyi +11 -3
  26. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/src/blazefl/core/server_handler.py +1 -1
  27. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/src/blazefl/core/server_handler.pyi +1 -1
  28. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/tests/test_contrib/test_fedavg.py +12 -12
  29. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/tests/test_core/test_client_trainer.py +5 -5
  30. blazefl-2.0.0.dev3/tests/test_utils/__init__.py +0 -0
  31. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/uv.lock +1 -1
  32. blazefl-2.0.0.dev1/examples/step-by-step-dsfl/algorithm/__init__.py +0 -3
  33. blazefl-2.0.0.dev1/src/blazefl/core/__init__.pyi +0 -6
  34. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/.github/FUNDING.yml +0 -0
  35. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  36. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  37. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/.github/dependabot.yml +0 -0
  38. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/.github/workflows/ci.yaml +0 -0
  39. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/.github/workflows/publish.yaml +0 -0
  40. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/.github/workflows/sphinx.yaml +0 -0
  41. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/.gitignore +0 -0
  42. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/.pre-commit-config.yaml +0 -0
  43. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/.python-version +0 -0
  44. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/CODE_OF_CONDUCT.md +0 -0
  45. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/LICENSE +0 -0
  46. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/README.md +0 -0
  47. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/docs/Makefile +0 -0
  48. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/docs/imgs/architecture.png +0 -0
  49. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/docs/imgs/benchmark_cnn.png +0 -0
  50. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/docs/imgs/benchmark_resnet18.png +0 -0
  51. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/docs/imgs/logo.svg +0 -0
  52. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/docs/imgs/logo_square.svg +0 -0
  53. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/docs/imgs/ogp.png +0 -0
  54. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/docs/make.bat +0 -0
  55. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/docs/source/_static/favicon.ico +0 -0
  56. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/docs/source/_static/logo.png +0 -0
  57. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/docs/source/_static/logo_square.png +0 -0
  58. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/docs/source/_templates/autosummary/class.rst +0 -0
  59. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/docs/source/_templates/autosummary/module.rst +0 -0
  60. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/docs/source/benchmark.rst +0 -0
  61. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/docs/source/conf.py +0 -0
  62. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/docs/source/contribute.rst +0 -0
  63. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/docs/source/example.rst +0 -0
  64. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/docs/source/index.rst +0 -0
  65. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/docs/source/install.rst +0 -0
  66. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/docs/source/overview.rst +0 -0
  67. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/docs/source/reference.rst +0 -0
  68. {blazefl-2.0.0.dev1/examples/quickstart-fedavg → blazefl-2.0.0.dev3/examples/experimental-freethreaded}/.gitignore +0 -0
  69. /blazefl-2.0.0.dev1/src/blazefl/__init__.py → /blazefl-2.0.0.dev3/examples/experimental-freethreaded/README.md +0 -0
  70. {blazefl-2.0.0.dev1/examples/quickstart-fedavg → blazefl-2.0.0.dev3/examples/experimental-freethreaded}/dataset/__init__.py +0 -0
  71. {blazefl-2.0.0.dev1/examples/quickstart-fedavg → blazefl-2.0.0.dev3/examples/experimental-freethreaded}/dataset/dataset.py +0 -0
  72. {blazefl-2.0.0.dev1/examples/quickstart-fedavg → blazefl-2.0.0.dev3/examples/experimental-freethreaded}/dataset/functional.py +0 -0
  73. {blazefl-2.0.0.dev1/examples/quickstart-fedavg → blazefl-2.0.0.dev3/examples/experimental-freethreaded}/models/__init__.py +0 -0
  74. {blazefl-2.0.0.dev1/examples/quickstart-fedavg → blazefl-2.0.0.dev3/examples/experimental-freethreaded}/models/selector.py +0 -0
  75. {blazefl-2.0.0.dev1/examples/step-by-step-dsfl → blazefl-2.0.0.dev3/examples/quickstart-fedavg}/.gitignore +0 -0
  76. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/examples/quickstart-fedavg/.python-version +0 -0
  77. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/examples/quickstart-fedavg/Makefile +0 -0
  78. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/examples/quickstart-fedavg/README.md +0 -0
  79. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/examples/quickstart-fedavg/config/config.yaml +0 -0
  80. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/examples/quickstart-fedavg/pyproject.toml +0 -0
  81. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/examples/step-by-step-dsfl/.python-version +0 -0
  82. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/examples/step-by-step-dsfl/Makefile +0 -0
  83. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/examples/step-by-step-dsfl/README.md +0 -0
  84. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/examples/step-by-step-dsfl/config/algorithm/dsfl.yaml +0 -0
  85. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/examples/step-by-step-dsfl/config/config.yaml +0 -0
  86. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/examples/step-by-step-dsfl/dataset/__init__.py +0 -0
  87. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/examples/step-by-step-dsfl/dataset/dataset.py +0 -0
  88. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/examples/step-by-step-dsfl/dataset/functional.py +0 -0
  89. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/examples/step-by-step-dsfl/models/__init__.py +0 -0
  90. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/examples/step-by-step-dsfl/models/cnn.py +0 -0
  91. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/examples/step-by-step-dsfl/models/selector.py +0 -0
  92. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/examples/step-by-step-dsfl/pyproject.toml +0 -0
  93. {blazefl-2.0.0.dev1/tests → blazefl-2.0.0.dev3/src/blazefl}/__init__.py +0 -0
  94. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/src/blazefl/core/model_selector.py +0 -0
  95. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/src/blazefl/core/model_selector.pyi +0 -0
  96. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/src/blazefl/core/partitioned_dataset.py +0 -0
  97. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/src/blazefl/core/partitioned_dataset.pyi +0 -0
  98. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/src/blazefl/py.typed +0 -0
  99. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/src/blazefl/utils/__init__.py +0 -0
  100. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/src/blazefl/utils/__init__.pyi +0 -0
  101. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/src/blazefl/utils/dataset.py +0 -0
  102. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/src/blazefl/utils/dataset.pyi +0 -0
  103. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/src/blazefl/utils/seed.py +0 -0
  104. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/src/blazefl/utils/seed.pyi +0 -0
  105. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/src/blazefl/utils/serialize.py +0 -0
  106. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/src/blazefl/utils/serialize.pyi +0 -0
  107. {blazefl-2.0.0.dev1/tests/test_contrib → blazefl-2.0.0.dev3/tests}/__init__.py +0 -0
  108. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/tests/conftest.py +0 -0
  109. {blazefl-2.0.0.dev1/tests/test_core → blazefl-2.0.0.dev3/tests/test_contrib}/__init__.py +0 -0
  110. {blazefl-2.0.0.dev1/tests/test_utils → blazefl-2.0.0.dev3/tests/test_core}/__init__.py +0 -0
  111. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/tests/test_core/test_model_selector.py +0 -0
  112. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/tests/test_core/test_partitioned_dataset.py +0 -0
  113. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/tests/test_utils/test_dataset.py +0 -0
  114. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/tests/test_utils/test_seed.py +0 -0
  115. {blazefl-2.0.0.dev1 → blazefl-2.0.0.dev3}/tests/test_utils/test_serialize.py +0 -0
@@ -9,4 +9,4 @@ test:
9
9
  pytest -v tests
10
10
 
11
11
  stubgen:
12
- stubgen -m blazefl.core -m blazefl.utils --no-analysis -o src
12
+ stubgen -p blazefl.core -p blazefl.utils --no-analysis -o src
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: blazefl
3
- Version: 2.0.0.dev1
3
+ Version: 2.0.0.dev3
4
4
  Summary: A blazing-fast and lightweight simulation framework for Federated Learning.
5
5
  Author-email: kitsuyaazuma <kitsuyaazuma@gmail.com>
6
6
  License-File: LICENSE
@@ -0,0 +1,6 @@
1
+ format:
2
+ ruff format .
3
+
4
+ lint:
5
+ ruff check . --fix
6
+ mypy .
@@ -0,0 +1,17 @@
1
+ model_name: cnn
2
+ num_clients: 100
3
+ global_round: 5
4
+ sample_ratio: 1.0
5
+ partition: shards
6
+ num_shards: 200
7
+ dir_alpha: 1.0
8
+ seed: 42
9
+ epochs: 5
10
+ lr: 0.1
11
+ batch_size: 50
12
+ num_parallels: 10
13
+ dataset_root_dir: /tmp/experimental-freethreaded/dataset
14
+ dataset_split_dir: /tmp/experimental-freethreaded/split
15
+ share_dir: /tmp/experimental-freethreaded/share
16
+ state_dir: /tmp/experimental-freethreaded/state
17
+ execution_mode: multi-thread
@@ -0,0 +1,219 @@
1
+ import logging
2
+ from copy import deepcopy
3
+ from datetime import datetime
4
+ from pathlib import Path
5
+
6
+ import hydra
7
+ import torch
8
+ import torch.multiprocessing as mp
9
+ from blazefl.contrib import (
10
+ FedAvgParallelClientTrainer,
11
+ FedAvgSerialClientTrainer,
12
+ FedAvgServerHandler,
13
+ )
14
+ from blazefl.contrib.fedavg import FedAvgDownlinkPackage, FedAvgUplinkPackage
15
+ from blazefl.core import ModelSelector, MultiThreadClientTrainer, PartitionedDataset
16
+ from blazefl.utils import seed_everything
17
+ from omegaconf import DictConfig, OmegaConf
18
+
19
+ from dataset import PartitionedCIFAR10
20
+ from models import FedAvgModelSelector
21
+
22
+
23
+ class FedAvgMultiThreadClientTrainer(
24
+ MultiThreadClientTrainer[
25
+ FedAvgUplinkPackage,
26
+ FedAvgDownlinkPackage,
27
+ ]
28
+ ):
29
+ def __init__(
30
+ self,
31
+ model_selector: ModelSelector,
32
+ model_name: str,
33
+ dataset: PartitionedDataset,
34
+ device: str,
35
+ num_clients: int,
36
+ epochs: int,
37
+ batch_size: int,
38
+ lr: float,
39
+ seed: int,
40
+ num_parallels: int,
41
+ ) -> None:
42
+ self.num_parallels = num_parallels
43
+ self.device = device
44
+ if self.device == "cuda":
45
+ self.device_count = torch.cuda.device_count()
46
+ self.cache: list[FedAvgUplinkPackage] = []
47
+
48
+ self.model_selector = model_selector
49
+ self.model_name = model_name
50
+ self.dataset = dataset
51
+ self.epochs = epochs
52
+ self.batch_size = batch_size
53
+ self.lr = lr
54
+ self.num_clients = num_clients
55
+ self.seed = seed
56
+
57
+ def process_client(
58
+ self,
59
+ cid: int,
60
+ device: str,
61
+ payload: FedAvgDownlinkPackage,
62
+ ) -> FedAvgUplinkPackage:
63
+ model = self.model_selector.select_model(self.model_name)
64
+ train_loader = self.dataset.get_dataloader(
65
+ type_="train",
66
+ cid=cid,
67
+ batch_size=self.batch_size,
68
+ )
69
+ package = FedAvgParallelClientTrainer.train(
70
+ model=model,
71
+ model_parameters=payload.model_parameters,
72
+ train_loader=train_loader,
73
+ device=device,
74
+ epochs=self.epochs,
75
+ lr=self.lr,
76
+ )
77
+ return package
78
+
79
+ def uplink_package(self) -> list[FedAvgUplinkPackage]:
80
+ package = deepcopy(self.cache)
81
+ self.cache = []
82
+ return package
83
+
84
+
85
+ class FedAvgPipeline:
86
+ def __init__(
87
+ self,
88
+ handler: FedAvgServerHandler,
89
+ trainer: FedAvgSerialClientTrainer
90
+ | FedAvgParallelClientTrainer
91
+ | FedAvgMultiThreadClientTrainer,
92
+ ) -> None:
93
+ self.handler = handler
94
+ self.trainer = trainer
95
+
96
+ def main(self):
97
+ while not self.handler.if_stop():
98
+ round_ = self.handler.round
99
+ # server side
100
+ sampled_clients = self.handler.sample_clients()
101
+ broadcast = self.handler.downlink_package()
102
+
103
+ # client side
104
+ self.trainer.local_process(broadcast, sampled_clients)
105
+ uploads = self.trainer.uplink_package()
106
+
107
+ # server side
108
+ for pack in uploads:
109
+ self.handler.load(pack)
110
+
111
+ summary = self.handler.get_summary()
112
+ formatted_summary = ", ".join(f"{k}: {v:.3f}" for k, v in summary.items())
113
+ logging.info(f"round: {round_}, {formatted_summary}")
114
+
115
+ logging.info("done!")
116
+
117
+
118
+ @hydra.main(version_base=None, config_path="config", config_name="config")
119
+ def main(cfg: DictConfig):
120
+ print(OmegaConf.to_yaml(cfg))
121
+
122
+ timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
123
+ dataset_root_dir = Path(cfg.dataset_root_dir)
124
+ dataset_split_dir = dataset_root_dir.joinpath(timestamp)
125
+ share_dir = Path(cfg.share_dir).joinpath(timestamp)
126
+ state_dir = Path(cfg.state_dir).joinpath(timestamp)
127
+
128
+ device = "cpu"
129
+ if torch.cuda.is_available():
130
+ device = "cuda"
131
+ elif torch.backends.mps.is_available():
132
+ device = "mps"
133
+ logging.info(f"device: {device}")
134
+
135
+ seed_everything(cfg.seed, device=device)
136
+
137
+ dataset = PartitionedCIFAR10(
138
+ root=dataset_root_dir,
139
+ path=dataset_split_dir,
140
+ num_clients=cfg.num_clients,
141
+ seed=cfg.seed,
142
+ partition=cfg.partition,
143
+ num_shards=cfg.num_shards,
144
+ dir_alpha=cfg.dir_alpha,
145
+ )
146
+ model_selector = FedAvgModelSelector(num_classes=10)
147
+
148
+ handler = FedAvgServerHandler(
149
+ model_selector=model_selector,
150
+ model_name=cfg.model_name,
151
+ dataset=dataset,
152
+ global_round=cfg.global_round,
153
+ num_clients=cfg.num_clients,
154
+ device=device,
155
+ sample_ratio=cfg.sample_ratio,
156
+ batch_size=cfg.batch_size,
157
+ )
158
+ trainer: (
159
+ FedAvgSerialClientTrainer
160
+ | FedAvgParallelClientTrainer
161
+ | FedAvgMultiThreadClientTrainer
162
+ | None
163
+ ) = None
164
+ match cfg.execution_mode:
165
+ case "serial":
166
+ trainer = FedAvgSerialClientTrainer(
167
+ model_selector=model_selector,
168
+ model_name=cfg.model_name,
169
+ dataset=dataset,
170
+ device=device,
171
+ num_clients=cfg.num_clients,
172
+ epochs=cfg.epochs,
173
+ lr=cfg.lr,
174
+ batch_size=cfg.batch_size,
175
+ )
176
+ case "multi-process":
177
+ trainer = FedAvgParallelClientTrainer(
178
+ model_selector=model_selector,
179
+ model_name=cfg.model_name,
180
+ dataset=dataset,
181
+ share_dir=share_dir,
182
+ state_dir=state_dir,
183
+ seed=cfg.seed,
184
+ device=device,
185
+ num_clients=cfg.num_clients,
186
+ epochs=cfg.epochs,
187
+ lr=cfg.lr,
188
+ batch_size=cfg.batch_size,
189
+ num_parallels=cfg.num_parallels,
190
+ )
191
+ case "multi-thread":
192
+ trainer = FedAvgMultiThreadClientTrainer(
193
+ model_selector=model_selector,
194
+ model_name=cfg.model_name,
195
+ dataset=dataset,
196
+ device=device,
197
+ num_clients=cfg.num_clients,
198
+ epochs=cfg.epochs,
199
+ lr=cfg.lr,
200
+ batch_size=cfg.batch_size,
201
+ num_parallels=cfg.num_parallels,
202
+ seed=cfg.seed,
203
+ )
204
+ case _:
205
+ raise ValueError(f"Invalid execution mode: {cfg.execution_mode}")
206
+ pipeline = FedAvgPipeline(handler=handler, trainer=trainer)
207
+ try:
208
+ pipeline.main()
209
+ except KeyboardInterrupt:
210
+ logging.info("KeyboardInterrupt: Stopping the pipeline.")
211
+ except Exception as e:
212
+ logging.exception(f"An error occurred: {e}")
213
+
214
+
215
+ if __name__ == "__main__":
216
+ # NOTE: To use CUDA with multiprocessing, you must use the 'spawn' start method
217
+ mp.set_start_method("spawn")
218
+
219
+ main()
@@ -0,0 +1,37 @@
1
+ [project]
2
+ name = "experimental-freethreaded"
3
+ version = "0.1.0"
4
+ description = "Add your description here"
5
+ readme = "README.md"
6
+ requires-python = ">=3.13"
7
+ dependencies = [
8
+ "blazefl>=2.0.0dev2",
9
+ "hydra-core>=1.3.2",
10
+ "torch>=2.7.1",
11
+ "torchvision>=0.22.1",
12
+ ]
13
+
14
+ [tool.basedpyright]
15
+ typeCheckingMode = "standard"
16
+
17
+ [[tool.mypy.overrides]]
18
+ module = ["torchvision.*"]
19
+ ignore_missing_imports = true
20
+
21
+ [tool.ruff.lint]
22
+ select = [
23
+ "E", # pycodestyle
24
+ "F", # Pyflakes
25
+ "UP", # pyupgrade
26
+ "B", # flake8-bugbear
27
+ "SIM", # flake8-simplify
28
+ "I", # isort
29
+ ]
30
+ ignore = []
31
+ fixable = ["ALL"]
32
+
33
+ [dependency-groups]
34
+ dev = [
35
+ "mypy>=1.16.0",
36
+ "types-tqdm>=4.67.0.20250516",
37
+ ]