flwr-nightly 1.11.0.dev20240828__py3-none-any.whl → 1.11.1.dev20240911__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.
Potentially problematic release.
This version of flwr-nightly might be problematic. Click here for more details.
- flwr/cli/new/new.py +23 -37
- flwr/cli/new/templates/app/code/client.huggingface.py.tpl +19 -29
- flwr/cli/new/templates/app/code/client.tensorflow.py.tpl +0 -3
- flwr/cli/new/templates/app/code/server.huggingface.py.tpl +18 -3
- flwr/cli/new/templates/app/code/task.huggingface.py.tpl +16 -13
- flwr/cli/new/templates/app/pyproject.huggingface.toml.tpl +9 -1
- flwr/client/__init__.py +0 -4
- flwr/client/client_app.py +2 -2
- flwr/client/grpc_rere_client/client_interceptor.py +15 -7
- flwr/common/record/recordset.py +1 -1
- flwr/common/record/typeddict.py +24 -1
- flwr/common/telemetry.py +36 -30
- flwr/server/__init__.py +0 -4
- flwr/server/compat/app.py +0 -5
- flwr/server/driver/grpc_driver.py +1 -3
- flwr/server/superlink/fleet/grpc_rere/server_interceptor.py +2 -1
- flwr/server/superlink/fleet/vce/backend/raybackend.py +21 -12
- flwr/simulation/ray_transport/ray_actor.py +2 -2
- flwr/simulation/run_simulation.py +37 -8
- flwr/superexec/__init__.py +0 -6
- flwr/superexec/app.py +3 -1
- {flwr_nightly-1.11.0.dev20240828.dist-info → flwr_nightly-1.11.1.dev20240911.dist-info}/METADATA +1 -1
- {flwr_nightly-1.11.0.dev20240828.dist-info → flwr_nightly-1.11.1.dev20240911.dist-info}/RECORD +26 -26
- flwr_nightly-1.11.1.dev20240911.dist-info/entry_points.txt +10 -0
- flwr_nightly-1.11.0.dev20240828.dist-info/entry_points.txt +0 -10
- {flwr_nightly-1.11.0.dev20240828.dist-info → flwr_nightly-1.11.1.dev20240911.dist-info}/LICENSE +0 -0
- {flwr_nightly-1.11.0.dev20240828.dist-info → flwr_nightly-1.11.1.dev20240911.dist-info}/WHEEL +0 -0
flwr/cli/new/new.py
CHANGED
|
@@ -136,36 +136,23 @@ def new(
|
|
|
136
136
|
username = prompt_text("Please provide your Flower username")
|
|
137
137
|
|
|
138
138
|
if framework is not None:
|
|
139
|
-
|
|
139
|
+
framework_str = str(framework.value)
|
|
140
140
|
else:
|
|
141
|
-
|
|
141
|
+
framework_str = prompt_options(
|
|
142
142
|
"Please select ML framework by typing in the number",
|
|
143
143
|
[mlf.value for mlf in MlFramework],
|
|
144
144
|
)
|
|
145
|
-
selected_value = [
|
|
146
|
-
name
|
|
147
|
-
for name, value in vars(MlFramework).items()
|
|
148
|
-
if value == framework_value
|
|
149
|
-
]
|
|
150
|
-
framework_str_upper = selected_value[0]
|
|
151
|
-
|
|
152
|
-
framework_str = framework_str_upper.lower()
|
|
153
145
|
|
|
154
146
|
llm_challenge_str = None
|
|
155
|
-
if framework_str ==
|
|
147
|
+
if framework_str == MlFramework.FLOWERTUNE:
|
|
156
148
|
llm_challenge_value = prompt_options(
|
|
157
149
|
"Please select LLM challenge by typing in the number",
|
|
158
150
|
sorted([challenge.value for challenge in LlmChallengeName]),
|
|
159
151
|
)
|
|
160
|
-
|
|
161
|
-
name
|
|
162
|
-
for name, value in vars(LlmChallengeName).items()
|
|
163
|
-
if value == llm_challenge_value
|
|
164
|
-
]
|
|
165
|
-
llm_challenge_str = selected_value[0]
|
|
166
|
-
llm_challenge_str = llm_challenge_str.lower()
|
|
152
|
+
llm_challenge_str = llm_challenge_value.lower()
|
|
167
153
|
|
|
168
|
-
|
|
154
|
+
if framework_str == MlFramework.BASELINE:
|
|
155
|
+
framework_str = "baseline"
|
|
169
156
|
|
|
170
157
|
print(
|
|
171
158
|
typer.style(
|
|
@@ -176,19 +163,21 @@ def new(
|
|
|
176
163
|
)
|
|
177
164
|
|
|
178
165
|
context = {
|
|
179
|
-
"framework_str":
|
|
166
|
+
"framework_str": framework_str,
|
|
180
167
|
"import_name": import_name.replace("-", "_"),
|
|
181
168
|
"package_name": package_name,
|
|
182
169
|
"project_name": app_name,
|
|
183
170
|
"username": username,
|
|
184
171
|
}
|
|
185
172
|
|
|
173
|
+
template_name = framework_str.lower()
|
|
174
|
+
|
|
186
175
|
# List of files to render
|
|
187
176
|
if llm_challenge_str:
|
|
188
177
|
files = {
|
|
189
178
|
".gitignore": {"template": "app/.gitignore.tpl"},
|
|
190
|
-
"pyproject.toml": {"template": f"app/pyproject.{
|
|
191
|
-
"README.md": {"template": f"app/README.{
|
|
179
|
+
"pyproject.toml": {"template": f"app/pyproject.{template_name}.toml.tpl"},
|
|
180
|
+
"README.md": {"template": f"app/README.{template_name}.md.tpl"},
|
|
192
181
|
f"{import_name}/__init__.py": {"template": "app/code/__init__.py.tpl"},
|
|
193
182
|
f"{import_name}/server_app.py": {
|
|
194
183
|
"template": "app/code/flwr_tune/server_app.py.tpl"
|
|
@@ -196,7 +185,6 @@ def new(
|
|
|
196
185
|
f"{import_name}/client_app.py": {
|
|
197
186
|
"template": "app/code/flwr_tune/client_app.py.tpl"
|
|
198
187
|
},
|
|
199
|
-
f"{import_name}/app.py": {"template": "app/code/flwr_tune/app.py.tpl"},
|
|
200
188
|
f"{import_name}/models.py": {
|
|
201
189
|
"template": "app/code/flwr_tune/models.py.tpl"
|
|
202
190
|
},
|
|
@@ -236,44 +224,42 @@ def new(
|
|
|
236
224
|
files = {
|
|
237
225
|
".gitignore": {"template": "app/.gitignore.tpl"},
|
|
238
226
|
"README.md": {"template": "app/README.md.tpl"},
|
|
239
|
-
"pyproject.toml": {"template": f"app/pyproject.{
|
|
227
|
+
"pyproject.toml": {"template": f"app/pyproject.{template_name}.toml.tpl"},
|
|
240
228
|
f"{import_name}/__init__.py": {"template": "app/code/__init__.py.tpl"},
|
|
241
229
|
f"{import_name}/server_app.py": {
|
|
242
|
-
"template": f"app/code/server.{
|
|
230
|
+
"template": f"app/code/server.{template_name}.py.tpl"
|
|
243
231
|
},
|
|
244
232
|
f"{import_name}/client_app.py": {
|
|
245
|
-
"template": f"app/code/client.{
|
|
233
|
+
"template": f"app/code/client.{template_name}.py.tpl"
|
|
246
234
|
},
|
|
247
235
|
}
|
|
248
236
|
|
|
249
237
|
# Depending on the framework, generate task.py file
|
|
250
238
|
frameworks_with_tasks = [
|
|
251
|
-
MlFramework.PYTORCH.value
|
|
252
|
-
MlFramework.JAX.value
|
|
253
|
-
MlFramework.HUGGINGFACE.value
|
|
254
|
-
MlFramework.MLX.value
|
|
255
|
-
MlFramework.TENSORFLOW.value
|
|
239
|
+
MlFramework.PYTORCH.value,
|
|
240
|
+
MlFramework.JAX.value,
|
|
241
|
+
MlFramework.HUGGINGFACE.value,
|
|
242
|
+
MlFramework.MLX.value,
|
|
243
|
+
MlFramework.TENSORFLOW.value,
|
|
256
244
|
]
|
|
257
245
|
if framework_str in frameworks_with_tasks:
|
|
258
246
|
files[f"{import_name}/task.py"] = {
|
|
259
|
-
"template": f"app/code/task.{
|
|
247
|
+
"template": f"app/code/task.{template_name}.py.tpl"
|
|
260
248
|
}
|
|
261
249
|
|
|
262
|
-
if
|
|
250
|
+
if framework_str == "baseline":
|
|
263
251
|
# Include additional files for baseline template
|
|
264
252
|
for file_name in ["model", "dataset", "strategy", "utils", "__init__"]:
|
|
265
253
|
files[f"{import_name}/{file_name}.py"] = {
|
|
266
|
-
"template": f"app/code/{file_name}.{
|
|
254
|
+
"template": f"app/code/{file_name}.{template_name}.py.tpl"
|
|
267
255
|
}
|
|
268
256
|
|
|
269
257
|
# Replace README.md
|
|
270
|
-
files["README.md"]["template"] = f"app/README.{
|
|
258
|
+
files["README.md"]["template"] = f"app/README.{template_name}.md.tpl"
|
|
271
259
|
|
|
272
260
|
# Add LICENSE
|
|
273
261
|
files["LICENSE"] = {"template": "app/LICENSE.tpl"}
|
|
274
262
|
|
|
275
|
-
context["framework_str"] = "baseline"
|
|
276
|
-
|
|
277
263
|
for file_path, value in files.items():
|
|
278
264
|
render_and_create(
|
|
279
265
|
file_path=project_dir / file_path,
|
|
@@ -1,18 +1,11 @@
|
|
|
1
1
|
"""$project_name: A Flower / $framework_str app."""
|
|
2
2
|
|
|
3
|
+
import torch
|
|
3
4
|
from flwr.client import ClientApp, NumPyClient
|
|
4
5
|
from flwr.common import Context
|
|
5
6
|
from transformers import AutoModelForSequenceClassification
|
|
6
7
|
|
|
7
|
-
from $import_name.task import
|
|
8
|
-
get_weights,
|
|
9
|
-
load_data,
|
|
10
|
-
set_weights,
|
|
11
|
-
train,
|
|
12
|
-
test,
|
|
13
|
-
CHECKPOINT,
|
|
14
|
-
DEVICE,
|
|
15
|
-
)
|
|
8
|
+
from $import_name.task import get_weights, load_data, set_weights, test, train
|
|
16
9
|
|
|
17
10
|
|
|
18
11
|
# Flower client
|
|
@@ -22,37 +15,34 @@ class FlowerClient(NumPyClient):
|
|
|
22
15
|
self.trainloader = trainloader
|
|
23
16
|
self.testloader = testloader
|
|
24
17
|
self.local_epochs = local_epochs
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
return get_weights(self.net)
|
|
28
|
-
|
|
29
|
-
def set_parameters(self, parameters):
|
|
30
|
-
set_weights(self.net, parameters)
|
|
18
|
+
self.device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
|
|
19
|
+
self.net.to(self.device)
|
|
31
20
|
|
|
32
21
|
def fit(self, parameters, config):
|
|
33
|
-
self.
|
|
34
|
-
train(
|
|
35
|
-
|
|
36
|
-
self.trainloader,
|
|
37
|
-
epochs=self.local_epochs,
|
|
38
|
-
)
|
|
39
|
-
return self.get_parameters(config={}), len(self.trainloader), {}
|
|
22
|
+
set_weights(self.net, parameters)
|
|
23
|
+
train(self.net, self.trainloader, epochs=self.local_epochs, device=self.device)
|
|
24
|
+
return get_weights(self.net), len(self.trainloader), {}
|
|
40
25
|
|
|
41
26
|
def evaluate(self, parameters, config):
|
|
42
|
-
self.
|
|
43
|
-
loss, accuracy = test(self.net, self.testloader)
|
|
27
|
+
set_weights(self.net, parameters)
|
|
28
|
+
loss, accuracy = test(self.net, self.testloader, self.device)
|
|
44
29
|
return float(loss), len(self.testloader), {"accuracy": accuracy}
|
|
45
30
|
|
|
46
31
|
|
|
47
32
|
def client_fn(context: Context):
|
|
48
|
-
# Load model and data
|
|
49
|
-
net = AutoModelForSequenceClassification.from_pretrained(
|
|
50
|
-
CHECKPOINT, num_labels=2
|
|
51
|
-
).to(DEVICE)
|
|
52
33
|
|
|
34
|
+
# Get this client's dataset partition
|
|
53
35
|
partition_id = context.node_config["partition-id"]
|
|
54
36
|
num_partitions = context.node_config["num-partitions"]
|
|
55
|
-
|
|
37
|
+
model_name = context.run_config["model-name"]
|
|
38
|
+
trainloader, valloader = load_data(partition_id, num_partitions, model_name)
|
|
39
|
+
|
|
40
|
+
# Load model
|
|
41
|
+
num_labels = context.run_config["num-labels"]
|
|
42
|
+
net = AutoModelForSequenceClassification.from_pretrained(
|
|
43
|
+
model_name, num_labels=num_labels
|
|
44
|
+
)
|
|
45
|
+
|
|
56
46
|
local_epochs = context.run_config["local-epochs"]
|
|
57
47
|
|
|
58
48
|
# Return Client instance
|
|
@@ -17,9 +17,6 @@ class FlowerClient(NumPyClient):
|
|
|
17
17
|
self.batch_size = batch_size
|
|
18
18
|
self.verbose = verbose
|
|
19
19
|
|
|
20
|
-
def get_parameters(self, config):
|
|
21
|
-
return self.model.get_weights()
|
|
22
|
-
|
|
23
20
|
def fit(self, parameters, config):
|
|
24
21
|
self.model.set_weights(parameters)
|
|
25
22
|
self.model.fit(
|
|
@@ -1,18 +1,33 @@
|
|
|
1
1
|
"""$project_name: A Flower / $framework_str app."""
|
|
2
2
|
|
|
3
|
-
from flwr.common import Context
|
|
4
|
-
from flwr.server.strategy import FedAvg
|
|
3
|
+
from flwr.common import Context, ndarrays_to_parameters
|
|
5
4
|
from flwr.server import ServerApp, ServerAppComponents, ServerConfig
|
|
5
|
+
from flwr.server.strategy import FedAvg
|
|
6
|
+
from transformers import AutoModelForSequenceClassification
|
|
7
|
+
|
|
8
|
+
from $import_name.task import get_weights
|
|
6
9
|
|
|
7
10
|
|
|
8
11
|
def server_fn(context: Context):
|
|
9
12
|
# Read from config
|
|
10
13
|
num_rounds = context.run_config["num-server-rounds"]
|
|
14
|
+
fraction_fit = context.run_config["fraction-fit"]
|
|
15
|
+
|
|
16
|
+
# Initialize global model
|
|
17
|
+
model_name = context.run_config["model-name"]
|
|
18
|
+
num_labels = context.run_config["num-labels"]
|
|
19
|
+
net = AutoModelForSequenceClassification.from_pretrained(
|
|
20
|
+
model_name, num_labels=num_labels
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
weights = get_weights(net)
|
|
24
|
+
initial_parameters = ndarrays_to_parameters(weights)
|
|
11
25
|
|
|
12
26
|
# Define strategy
|
|
13
27
|
strategy = FedAvg(
|
|
14
|
-
fraction_fit=
|
|
28
|
+
fraction_fit=fraction_fit,
|
|
15
29
|
fraction_evaluate=1.0,
|
|
30
|
+
initial_parameters=initial_parameters,
|
|
16
31
|
)
|
|
17
32
|
config = ServerConfig(num_rounds=num_rounds)
|
|
18
33
|
|
|
@@ -4,24 +4,25 @@ import warnings
|
|
|
4
4
|
from collections import OrderedDict
|
|
5
5
|
|
|
6
6
|
import torch
|
|
7
|
+
import transformers
|
|
8
|
+
from datasets.utils.logging import disable_progress_bar
|
|
7
9
|
from evaluate import load as load_metric
|
|
10
|
+
from flwr_datasets import FederatedDataset
|
|
11
|
+
from flwr_datasets.partitioner import IidPartitioner
|
|
8
12
|
from torch.optim import AdamW
|
|
9
13
|
from torch.utils.data import DataLoader
|
|
10
14
|
from transformers import AutoTokenizer, DataCollatorWithPadding
|
|
11
15
|
|
|
12
|
-
from flwr_datasets import FederatedDataset
|
|
13
|
-
from flwr_datasets.partitioner import IidPartitioner
|
|
14
|
-
|
|
15
|
-
|
|
16
16
|
warnings.filterwarnings("ignore", category=UserWarning)
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
warnings.filterwarnings("ignore", category=FutureWarning)
|
|
18
|
+
disable_progress_bar()
|
|
19
|
+
transformers.logging.set_verbosity_error()
|
|
19
20
|
|
|
20
21
|
|
|
21
22
|
fds = None # Cache FederatedDataset
|
|
22
23
|
|
|
23
24
|
|
|
24
|
-
def load_data(partition_id: int, num_partitions: int):
|
|
25
|
+
def load_data(partition_id: int, num_partitions: int, model_name: str):
|
|
25
26
|
"""Load IMDB data (training and eval)"""
|
|
26
27
|
# Only initialize `FederatedDataset` once
|
|
27
28
|
global fds
|
|
@@ -35,10 +36,12 @@ def load_data(partition_id: int, num_partitions: int):
|
|
|
35
36
|
# Divide data: 80% train, 20% test
|
|
36
37
|
partition_train_test = partition.train_test_split(test_size=0.2, seed=42)
|
|
37
38
|
|
|
38
|
-
tokenizer = AutoTokenizer.from_pretrained(
|
|
39
|
+
tokenizer = AutoTokenizer.from_pretrained(model_name)
|
|
39
40
|
|
|
40
41
|
def tokenize_function(examples):
|
|
41
|
-
return tokenizer(
|
|
42
|
+
return tokenizer(
|
|
43
|
+
examples["text"], truncation=True, add_special_tokens=True, max_length=512
|
|
44
|
+
)
|
|
42
45
|
|
|
43
46
|
partition_train_test = partition_train_test.map(tokenize_function, batched=True)
|
|
44
47
|
partition_train_test = partition_train_test.remove_columns("text")
|
|
@@ -59,12 +62,12 @@ def load_data(partition_id: int, num_partitions: int):
|
|
|
59
62
|
return trainloader, testloader
|
|
60
63
|
|
|
61
64
|
|
|
62
|
-
def train(net, trainloader, epochs):
|
|
65
|
+
def train(net, trainloader, epochs, device):
|
|
63
66
|
optimizer = AdamW(net.parameters(), lr=5e-5)
|
|
64
67
|
net.train()
|
|
65
68
|
for _ in range(epochs):
|
|
66
69
|
for batch in trainloader:
|
|
67
|
-
batch = {k: v.to(
|
|
70
|
+
batch = {k: v.to(device) for k, v in batch.items()}
|
|
68
71
|
outputs = net(**batch)
|
|
69
72
|
loss = outputs.loss
|
|
70
73
|
loss.backward()
|
|
@@ -72,12 +75,12 @@ def train(net, trainloader, epochs):
|
|
|
72
75
|
optimizer.zero_grad()
|
|
73
76
|
|
|
74
77
|
|
|
75
|
-
def test(net, testloader):
|
|
78
|
+
def test(net, testloader, device):
|
|
76
79
|
metric = load_metric("accuracy")
|
|
77
80
|
loss = 0
|
|
78
81
|
net.eval()
|
|
79
82
|
for batch in testloader:
|
|
80
|
-
batch = {k: v.to(
|
|
83
|
+
batch = {k: v.to(device) for k, v in batch.items()}
|
|
81
84
|
with torch.no_grad():
|
|
82
85
|
outputs = net(**batch)
|
|
83
86
|
logits = outputs.logits
|
|
@@ -8,7 +8,7 @@ version = "1.0.0"
|
|
|
8
8
|
description = ""
|
|
9
9
|
license = "Apache-2.0"
|
|
10
10
|
dependencies = [
|
|
11
|
-
"flwr[simulation]>=1.
|
|
11
|
+
"flwr[simulation]>=1.11.0",
|
|
12
12
|
"flwr-datasets>=0.3.0",
|
|
13
13
|
"torch==2.2.1",
|
|
14
14
|
"transformers>=4.30.0,<5.0",
|
|
@@ -29,10 +29,18 @@ clientapp = "$import_name.client_app:app"
|
|
|
29
29
|
|
|
30
30
|
[tool.flwr.app.config]
|
|
31
31
|
num-server-rounds = 3
|
|
32
|
+
fraction-fit = 0.5
|
|
32
33
|
local-epochs = 1
|
|
34
|
+
model-name = "prajjwal1/bert-tiny" # Set a larger model if you have access to more GPU resources
|
|
35
|
+
num-labels = 2
|
|
33
36
|
|
|
34
37
|
[tool.flwr.federations]
|
|
35
38
|
default = "localhost"
|
|
36
39
|
|
|
37
40
|
[tool.flwr.federations.localhost]
|
|
38
41
|
options.num-supernodes = 10
|
|
42
|
+
|
|
43
|
+
[tool.flwr.federations.localhost-gpu]
|
|
44
|
+
options.num-supernodes = 10
|
|
45
|
+
options.backend.client-resources.num-cpus = 4 # each ClientApp assumes to use 4CPUs
|
|
46
|
+
options.backend.client-resources.num-gpus = 0.25 # at most 4 ClientApps will run in a given GPU
|
flwr/client/__init__.py
CHANGED
|
@@ -20,8 +20,6 @@ from .app import start_numpy_client as start_numpy_client
|
|
|
20
20
|
from .client import Client as Client
|
|
21
21
|
from .client_app import ClientApp as ClientApp
|
|
22
22
|
from .numpy_client import NumPyClient as NumPyClient
|
|
23
|
-
from .supernode import run_client_app as run_client_app
|
|
24
|
-
from .supernode import run_supernode as run_supernode
|
|
25
23
|
from .typing import ClientFn as ClientFn
|
|
26
24
|
from .typing import ClientFnExt as ClientFnExt
|
|
27
25
|
|
|
@@ -32,8 +30,6 @@ __all__ = [
|
|
|
32
30
|
"ClientFnExt",
|
|
33
31
|
"NumPyClient",
|
|
34
32
|
"mod",
|
|
35
|
-
"run_client_app",
|
|
36
|
-
"run_supernode",
|
|
37
33
|
"start_client",
|
|
38
34
|
"start_numpy_client",
|
|
39
35
|
]
|
flwr/client/client_app.py
CHANGED
|
@@ -41,11 +41,11 @@ def _alert_erroneous_client_fn() -> None:
|
|
|
41
41
|
|
|
42
42
|
def _inspect_maybe_adapt_client_fn_signature(client_fn: ClientFnExt) -> ClientFnExt:
|
|
43
43
|
client_fn_args = inspect.signature(client_fn).parameters
|
|
44
|
-
first_arg = list(client_fn_args.keys())[0]
|
|
45
44
|
|
|
46
45
|
if len(client_fn_args) != 1:
|
|
47
46
|
_alert_erroneous_client_fn()
|
|
48
47
|
|
|
48
|
+
first_arg = list(client_fn_args.keys())[0]
|
|
49
49
|
first_arg_type = client_fn_args[first_arg].annotation
|
|
50
50
|
|
|
51
51
|
if first_arg_type is str or first_arg == "cid":
|
|
@@ -263,7 +263,7 @@ def _registration_error(fn_name: str) -> ValueError:
|
|
|
263
263
|
>>> class FlowerClient(NumPyClient):
|
|
264
264
|
>>> # ...
|
|
265
265
|
>>>
|
|
266
|
-
>>> def client_fn(
|
|
266
|
+
>>> def client_fn(context: Context):
|
|
267
267
|
>>> return FlowerClient().to_client()
|
|
268
268
|
>>>
|
|
269
269
|
>>> app = ClientApp(
|
|
@@ -17,11 +17,13 @@
|
|
|
17
17
|
|
|
18
18
|
import base64
|
|
19
19
|
import collections
|
|
20
|
+
from logging import WARNING
|
|
20
21
|
from typing import Any, Callable, Optional, Sequence, Tuple, Union
|
|
21
22
|
|
|
22
23
|
import grpc
|
|
23
24
|
from cryptography.hazmat.primitives.asymmetric import ec
|
|
24
25
|
|
|
26
|
+
from flwr.common.logger import log
|
|
25
27
|
from flwr.common.secure_aggregation.crypto.symmetric_encryption import (
|
|
26
28
|
bytes_to_public_key,
|
|
27
29
|
compute_hmac,
|
|
@@ -128,13 +130,12 @@ class AuthenticateClientInterceptor(grpc.UnaryUnaryClientInterceptor): # type:
|
|
|
128
130
|
if self.shared_secret is None:
|
|
129
131
|
raise RuntimeError("Failure to compute hmac")
|
|
130
132
|
|
|
133
|
+
message_bytes = request.SerializeToString(deterministic=True)
|
|
131
134
|
metadata.append(
|
|
132
135
|
(
|
|
133
136
|
_AUTH_TOKEN_HEADER,
|
|
134
137
|
base64.urlsafe_b64encode(
|
|
135
|
-
compute_hmac(
|
|
136
|
-
self.shared_secret, request.SerializeToString(True)
|
|
137
|
-
)
|
|
138
|
+
compute_hmac(self.shared_secret, message_bytes)
|
|
138
139
|
),
|
|
139
140
|
)
|
|
140
141
|
)
|
|
@@ -151,8 +152,15 @@ class AuthenticateClientInterceptor(grpc.UnaryUnaryClientInterceptor): # type:
|
|
|
151
152
|
server_public_key_bytes = base64.urlsafe_b64decode(
|
|
152
153
|
_get_value_from_tuples(_PUBLIC_KEY_HEADER, response.initial_metadata())
|
|
153
154
|
)
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
self.
|
|
157
|
-
|
|
155
|
+
|
|
156
|
+
if server_public_key_bytes != b"":
|
|
157
|
+
self.server_public_key = bytes_to_public_key(server_public_key_bytes)
|
|
158
|
+
else:
|
|
159
|
+
log(WARNING, "Can't get server public key, SuperLink may be offline")
|
|
160
|
+
|
|
161
|
+
if self.server_public_key is not None:
|
|
162
|
+
self.shared_secret = generate_shared_key(
|
|
163
|
+
self.private_key, self.server_public_key
|
|
164
|
+
)
|
|
165
|
+
|
|
158
166
|
return response
|
flwr/common/record/recordset.py
CHANGED
|
@@ -119,7 +119,7 @@ class RecordSet:
|
|
|
119
119
|
Let's see an example.
|
|
120
120
|
|
|
121
121
|
>>> from flwr.common import RecordSet
|
|
122
|
-
>>> from flwr.common import
|
|
122
|
+
>>> from flwr.common import ConfigsRecord, MetricsRecord, ParametersRecord
|
|
123
123
|
>>>
|
|
124
124
|
>>> # Let's begin with an empty record
|
|
125
125
|
>>> my_recordset = RecordSet()
|
flwr/common/record/typeddict.py
CHANGED
|
@@ -15,7 +15,18 @@
|
|
|
15
15
|
"""Typed dict base class for *Records."""
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
from typing import
|
|
18
|
+
from typing import (
|
|
19
|
+
Callable,
|
|
20
|
+
Dict,
|
|
21
|
+
Generic,
|
|
22
|
+
ItemsView,
|
|
23
|
+
Iterator,
|
|
24
|
+
KeysView,
|
|
25
|
+
MutableMapping,
|
|
26
|
+
TypeVar,
|
|
27
|
+
ValuesView,
|
|
28
|
+
cast,
|
|
29
|
+
)
|
|
19
30
|
|
|
20
31
|
K = TypeVar("K") # Key type
|
|
21
32
|
V = TypeVar("V") # Value type
|
|
@@ -73,3 +84,15 @@ class TypedDict(MutableMapping[K, V], Generic[K, V]):
|
|
|
73
84
|
if isinstance(other, dict):
|
|
74
85
|
return data == other
|
|
75
86
|
return NotImplemented
|
|
87
|
+
|
|
88
|
+
def keys(self) -> KeysView[K]:
|
|
89
|
+
"""D.keys() -> a set-like object providing a view on D's keys."""
|
|
90
|
+
return cast(Dict[K, V], self.__dict__["_data"]).keys()
|
|
91
|
+
|
|
92
|
+
def values(self) -> ValuesView[V]:
|
|
93
|
+
"""D.values() -> an object providing a view on D's values."""
|
|
94
|
+
return cast(Dict[K, V], self.__dict__["_data"]).values()
|
|
95
|
+
|
|
96
|
+
def items(self) -> ItemsView[K, V]:
|
|
97
|
+
"""D.items() -> a set-like object providing a view on D's items."""
|
|
98
|
+
return cast(Dict[K, V], self.__dict__["_data"]).items()
|
flwr/common/telemetry.py
CHANGED
|
@@ -132,53 +132,59 @@ class EventType(str, Enum):
|
|
|
132
132
|
# Ping
|
|
133
133
|
PING = auto()
|
|
134
134
|
|
|
135
|
-
#
|
|
135
|
+
# --- LEGACY FUNCTIONS -------------------------------------------------------------
|
|
136
|
+
|
|
137
|
+
# Legacy: `start_client` function
|
|
136
138
|
START_CLIENT_ENTER = auto()
|
|
137
139
|
START_CLIENT_LEAVE = auto()
|
|
138
140
|
|
|
139
|
-
#
|
|
141
|
+
# Legacy: `start_server` function
|
|
140
142
|
START_SERVER_ENTER = auto()
|
|
141
143
|
START_SERVER_LEAVE = auto()
|
|
142
144
|
|
|
143
|
-
#
|
|
144
|
-
|
|
145
|
-
|
|
145
|
+
# Legacy: `start_simulation` function
|
|
146
|
+
START_SIMULATION_ENTER = auto()
|
|
147
|
+
START_SIMULATION_LEAVE = auto()
|
|
146
148
|
|
|
147
|
-
#
|
|
148
|
-
RUN_FLEET_API_ENTER = auto()
|
|
149
|
-
RUN_FLEET_API_LEAVE = auto()
|
|
149
|
+
# --- `flwr` CLI -------------------------------------------------------------------
|
|
150
150
|
|
|
151
|
-
#
|
|
152
|
-
RUN_SUPERLINK_ENTER = auto()
|
|
153
|
-
RUN_SUPERLINK_LEAVE = auto()
|
|
151
|
+
# Not yet implemented
|
|
154
152
|
|
|
155
|
-
#
|
|
156
|
-
START_SIMULATION_ENTER = auto()
|
|
157
|
-
START_SIMULATION_LEAVE = auto()
|
|
153
|
+
# --- SuperExec --------------------------------------------------------------------
|
|
158
154
|
|
|
159
|
-
#
|
|
160
|
-
|
|
161
|
-
|
|
155
|
+
# SuperExec
|
|
156
|
+
RUN_SUPEREXEC_ENTER = auto()
|
|
157
|
+
RUN_SUPEREXEC_LEAVE = auto()
|
|
162
158
|
|
|
163
|
-
#
|
|
164
|
-
START_DRIVER_ENTER = auto()
|
|
165
|
-
START_DRIVER_LEAVE = auto()
|
|
159
|
+
# --- Simulation Engine ------------------------------------------------------------
|
|
166
160
|
|
|
167
|
-
# flower-
|
|
168
|
-
|
|
169
|
-
|
|
161
|
+
# CLI: flower-simulation
|
|
162
|
+
CLI_FLOWER_SIMULATION_ENTER = auto()
|
|
163
|
+
CLI_FLOWER_SIMULATION_LEAVE = auto()
|
|
170
164
|
|
|
171
|
-
#
|
|
172
|
-
|
|
173
|
-
|
|
165
|
+
# Python API: `run_simulation`
|
|
166
|
+
PYTHON_API_RUN_SIMULATION_ENTER = auto()
|
|
167
|
+
PYTHON_API_RUN_SIMULATION_LEAVE = auto()
|
|
174
168
|
|
|
175
|
-
#
|
|
169
|
+
# --- Deployment Engine ------------------------------------------------------------
|
|
170
|
+
|
|
171
|
+
# CLI: `flower-superlink`
|
|
172
|
+
RUN_SUPERLINK_ENTER = auto()
|
|
173
|
+
RUN_SUPERLINK_LEAVE = auto()
|
|
174
|
+
|
|
175
|
+
# CLI: `flower-supernode`
|
|
176
176
|
RUN_SUPERNODE_ENTER = auto()
|
|
177
177
|
RUN_SUPERNODE_LEAVE = auto()
|
|
178
178
|
|
|
179
|
-
#
|
|
180
|
-
|
|
181
|
-
|
|
179
|
+
# CLI: `flower-server-app`
|
|
180
|
+
RUN_SERVER_APP_ENTER = auto()
|
|
181
|
+
RUN_SERVER_APP_LEAVE = auto()
|
|
182
|
+
|
|
183
|
+
# --- DEPRECATED -------------------------------------------------------------------
|
|
184
|
+
|
|
185
|
+
# [DEPRECATED] CLI: `flower-client-app`
|
|
186
|
+
RUN_CLIENT_APP_ENTER = auto()
|
|
187
|
+
RUN_CLIENT_APP_LEAVE = auto()
|
|
182
188
|
|
|
183
189
|
|
|
184
190
|
# Use the ThreadPoolExecutor with max_workers=1 to have a queue
|
flwr/server/__init__.py
CHANGED
|
@@ -17,14 +17,12 @@
|
|
|
17
17
|
|
|
18
18
|
from . import strategy
|
|
19
19
|
from . import workflow as workflow
|
|
20
|
-
from .app import run_superlink as run_superlink
|
|
21
20
|
from .app import start_server as start_server
|
|
22
21
|
from .client_manager import ClientManager as ClientManager
|
|
23
22
|
from .client_manager import SimpleClientManager as SimpleClientManager
|
|
24
23
|
from .compat import LegacyContext as LegacyContext
|
|
25
24
|
from .driver import Driver as Driver
|
|
26
25
|
from .history import History as History
|
|
27
|
-
from .run_serverapp import run_server_app as run_server_app
|
|
28
26
|
from .server import Server as Server
|
|
29
27
|
from .server_app import ServerApp as ServerApp
|
|
30
28
|
from .server_config import ServerConfig as ServerConfig
|
|
@@ -40,8 +38,6 @@ __all__ = [
|
|
|
40
38
|
"ServerAppComponents",
|
|
41
39
|
"ServerConfig",
|
|
42
40
|
"SimpleClientManager",
|
|
43
|
-
"run_server_app",
|
|
44
|
-
"run_superlink",
|
|
45
41
|
"start_server",
|
|
46
42
|
"strategy",
|
|
47
43
|
"workflow",
|
flwr/server/compat/app.py
CHANGED
|
@@ -18,7 +18,6 @@
|
|
|
18
18
|
from logging import INFO
|
|
19
19
|
from typing import Optional
|
|
20
20
|
|
|
21
|
-
from flwr.common import EventType, event
|
|
22
21
|
from flwr.common.logger import log
|
|
23
22
|
from flwr.server.client_manager import ClientManager
|
|
24
23
|
from flwr.server.history import History
|
|
@@ -65,8 +64,6 @@ def start_driver( # pylint: disable=too-many-arguments, too-many-locals
|
|
|
65
64
|
hist : flwr.server.history.History
|
|
66
65
|
Object containing training and evaluation metrics.
|
|
67
66
|
"""
|
|
68
|
-
event(EventType.START_DRIVER_ENTER)
|
|
69
|
-
|
|
70
67
|
# Initialize the Driver API server and config
|
|
71
68
|
initialized_server, initialized_config = init_defaults(
|
|
72
69
|
server=server,
|
|
@@ -96,6 +93,4 @@ def start_driver( # pylint: disable=too-many-arguments, too-many-locals
|
|
|
96
93
|
f_stop.set()
|
|
97
94
|
thread.join()
|
|
98
95
|
|
|
99
|
-
event(EventType.START_SERVER_LEAVE)
|
|
100
|
-
|
|
101
96
|
return hist
|
|
@@ -21,7 +21,7 @@ from typing import Iterable, List, Optional, cast
|
|
|
21
21
|
|
|
22
22
|
import grpc
|
|
23
23
|
|
|
24
|
-
from flwr.common import DEFAULT_TTL,
|
|
24
|
+
from flwr.common import DEFAULT_TTL, Message, Metadata, RecordSet
|
|
25
25
|
from flwr.common.grpc import create_channel
|
|
26
26
|
from flwr.common.logger import log
|
|
27
27
|
from flwr.common.serde import (
|
|
@@ -94,7 +94,6 @@ class GrpcDriver(Driver):
|
|
|
94
94
|
|
|
95
95
|
This will not call GetRun.
|
|
96
96
|
"""
|
|
97
|
-
event(EventType.DRIVER_CONNECT)
|
|
98
97
|
if self._is_connected:
|
|
99
98
|
log(WARNING, "Already connected")
|
|
100
99
|
return
|
|
@@ -108,7 +107,6 @@ class GrpcDriver(Driver):
|
|
|
108
107
|
|
|
109
108
|
def _disconnect(self) -> None:
|
|
110
109
|
"""Disconnect from the Driver API."""
|
|
111
|
-
event(EventType.DRIVER_DISCONNECT)
|
|
112
110
|
if not self._is_connected:
|
|
113
111
|
log(DEBUG, "Already disconnected")
|
|
114
112
|
return
|
|
@@ -188,7 +188,8 @@ class AuthenticateServerInterceptor(grpc.ServerInterceptor): # type: ignore
|
|
|
188
188
|
self, public_key: ec.EllipticCurvePublicKey, request: Request, hmac_value: bytes
|
|
189
189
|
) -> bool:
|
|
190
190
|
shared_secret = generate_shared_key(self.server_private_key, public_key)
|
|
191
|
-
|
|
191
|
+
message_bytes = request.SerializeToString(deterministic=True)
|
|
192
|
+
return verify_hmac(shared_secret, message_bytes, hmac_value)
|
|
192
193
|
|
|
193
194
|
def _create_authenticated_node(
|
|
194
195
|
self,
|
|
@@ -52,16 +52,11 @@ class RayBackend(Backend):
|
|
|
52
52
|
|
|
53
53
|
# Validate client resources
|
|
54
54
|
self.client_resources_key = "client_resources"
|
|
55
|
-
client_resources = self._validate_client_resources(config=backend_config)
|
|
55
|
+
self.client_resources = self._validate_client_resources(config=backend_config)
|
|
56
56
|
|
|
57
|
-
#
|
|
58
|
-
actor_kwargs = self._validate_actor_arguments(config=backend_config)
|
|
59
|
-
|
|
60
|
-
self.pool = BasicActorPool(
|
|
61
|
-
actor_type=ClientAppActor,
|
|
62
|
-
client_resources=client_resources,
|
|
63
|
-
actor_kwargs=actor_kwargs,
|
|
64
|
-
)
|
|
57
|
+
# Valide actor resources
|
|
58
|
+
self.actor_kwargs = self._validate_actor_arguments(config=backend_config)
|
|
59
|
+
self.pool: Optional[BasicActorPool] = None
|
|
65
60
|
|
|
66
61
|
self.app_fn: Optional[Callable[[], ClientApp]] = None
|
|
67
62
|
|
|
@@ -122,14 +117,24 @@ class RayBackend(Backend):
|
|
|
122
117
|
@property
|
|
123
118
|
def num_workers(self) -> int:
|
|
124
119
|
"""Return number of actors in pool."""
|
|
125
|
-
return self.pool.num_actors
|
|
120
|
+
return self.pool.num_actors if self.pool else 0
|
|
126
121
|
|
|
127
122
|
def is_worker_idle(self) -> bool:
|
|
128
123
|
"""Report whether the pool has idle actors."""
|
|
129
|
-
return self.pool.is_actor_available()
|
|
124
|
+
return self.pool.is_actor_available() if self.pool else False
|
|
130
125
|
|
|
131
126
|
def build(self, app_fn: Callable[[], ClientApp]) -> None:
|
|
132
127
|
"""Build pool of Ray actors that this backend will submit jobs to."""
|
|
128
|
+
# Create Actor Pool
|
|
129
|
+
try:
|
|
130
|
+
self.pool = BasicActorPool(
|
|
131
|
+
actor_type=ClientAppActor,
|
|
132
|
+
client_resources=self.client_resources,
|
|
133
|
+
actor_kwargs=self.actor_kwargs,
|
|
134
|
+
)
|
|
135
|
+
except Exception as ex:
|
|
136
|
+
raise ex
|
|
137
|
+
|
|
133
138
|
self.pool.add_actors_to_pool(self.pool.actors_capacity)
|
|
134
139
|
# Set ClientApp callable that ray actors will use
|
|
135
140
|
self.app_fn = app_fn
|
|
@@ -146,6 +151,9 @@ class RayBackend(Backend):
|
|
|
146
151
|
"""
|
|
147
152
|
partition_id = context.node_config[PARTITION_ID_KEY]
|
|
148
153
|
|
|
154
|
+
if self.pool is None:
|
|
155
|
+
raise ValueError("The actor pool is empty, unfit to process messages.")
|
|
156
|
+
|
|
149
157
|
if self.app_fn is None:
|
|
150
158
|
raise ValueError(
|
|
151
159
|
"Unspecified function to load a `ClientApp`. "
|
|
@@ -179,6 +187,7 @@ class RayBackend(Backend):
|
|
|
179
187
|
|
|
180
188
|
def terminate(self) -> None:
|
|
181
189
|
"""Terminate all actors in actor pool."""
|
|
182
|
-
self.pool
|
|
190
|
+
if self.pool:
|
|
191
|
+
self.pool.terminate_all_actors()
|
|
183
192
|
ray.shutdown()
|
|
184
193
|
log(DEBUG, "Terminated %s", self.__class__.__name__)
|
|
@@ -124,14 +124,14 @@ def pool_size_from_resources(client_resources: Dict[str, Union[int, float]]) ->
|
|
|
124
124
|
WARNING,
|
|
125
125
|
"The ActorPool is empty. The system (CPUs=%s, GPUs=%s) "
|
|
126
126
|
"does not meet the criteria to host at least one client with resources:"
|
|
127
|
-
" %s. Lowering
|
|
127
|
+
" %s. Lowering these resources could help.",
|
|
128
128
|
num_cpus,
|
|
129
129
|
num_gpus,
|
|
130
130
|
client_resources,
|
|
131
131
|
)
|
|
132
132
|
raise ValueError(
|
|
133
133
|
"ActorPool is empty. Stopping Simulation. "
|
|
134
|
-
"Check
|
|
134
|
+
"Check `num_cpus` and/or `num_gpus` passed to the simulation engine"
|
|
135
135
|
)
|
|
136
136
|
|
|
137
137
|
return total_num_actors
|
|
@@ -109,6 +109,11 @@ def run_simulation_from_cli() -> None:
|
|
|
109
109
|
"""Run Simulation Engine from the CLI."""
|
|
110
110
|
args = _parse_args_run_simulation().parse_args()
|
|
111
111
|
|
|
112
|
+
event(
|
|
113
|
+
EventType.CLI_FLOWER_SIMULATION_ENTER,
|
|
114
|
+
event_details={"backend": args.backend, "num-supernodes": args.num_supernodes},
|
|
115
|
+
)
|
|
116
|
+
|
|
112
117
|
# Add warnings for deprecated server_app and client_app arguments
|
|
113
118
|
if args.server_app:
|
|
114
119
|
warn_deprecated_feature(
|
|
@@ -177,7 +182,9 @@ def run_simulation_from_cli() -> None:
|
|
|
177
182
|
client_app_attr = app_components["clientapp"]
|
|
178
183
|
server_app_attr = app_components["serverapp"]
|
|
179
184
|
|
|
180
|
-
override_config = parse_config_args(
|
|
185
|
+
override_config = parse_config_args(
|
|
186
|
+
[args.run_config] if args.run_config else args.run_config
|
|
187
|
+
)
|
|
181
188
|
fused_config = get_fused_config_from_dir(app_path, override_config)
|
|
182
189
|
app_dir = args.app
|
|
183
190
|
is_app = True
|
|
@@ -209,9 +216,11 @@ def run_simulation_from_cli() -> None:
|
|
|
209
216
|
app_dir=app_dir,
|
|
210
217
|
run=run,
|
|
211
218
|
enable_tf_gpu_growth=args.enable_tf_gpu_growth,
|
|
219
|
+
delay_start=args.delay_start,
|
|
212
220
|
verbose_logging=args.verbose,
|
|
213
221
|
server_app_run_config=fused_config,
|
|
214
222
|
is_app=is_app,
|
|
223
|
+
exit_event=EventType.CLI_FLOWER_SIMULATION_LEAVE,
|
|
215
224
|
)
|
|
216
225
|
|
|
217
226
|
|
|
@@ -265,6 +274,11 @@ def run_simulation(
|
|
|
265
274
|
When disabled, only INFO, WARNING and ERROR log messages will be shown. If
|
|
266
275
|
enabled, DEBUG-level logs will be displayed.
|
|
267
276
|
"""
|
|
277
|
+
event(
|
|
278
|
+
EventType.PYTHON_API_RUN_SIMULATION_ENTER,
|
|
279
|
+
event_details={"backend": backend_name, "num-supernodes": num_supernodes},
|
|
280
|
+
)
|
|
281
|
+
|
|
268
282
|
if enable_tf_gpu_growth:
|
|
269
283
|
warn_deprecated_feature_with_example(
|
|
270
284
|
"Passing `enable_tf_gpu_growth=True` is deprecated.",
|
|
@@ -282,6 +296,7 @@ def run_simulation(
|
|
|
282
296
|
backend_config=backend_config,
|
|
283
297
|
enable_tf_gpu_growth=enable_tf_gpu_growth,
|
|
284
298
|
verbose_logging=verbose_logging,
|
|
299
|
+
exit_event=EventType.PYTHON_API_RUN_SIMULATION_LEAVE,
|
|
285
300
|
)
|
|
286
301
|
|
|
287
302
|
|
|
@@ -295,7 +310,6 @@ def run_serverapp_th(
|
|
|
295
310
|
f_stop: threading.Event,
|
|
296
311
|
has_exception: threading.Event,
|
|
297
312
|
enable_tf_gpu_growth: bool,
|
|
298
|
-
delay_launch: int = 3,
|
|
299
313
|
) -> threading.Thread:
|
|
300
314
|
"""Run SeverApp in a thread."""
|
|
301
315
|
|
|
@@ -351,7 +365,6 @@ def run_serverapp_th(
|
|
|
351
365
|
server_app,
|
|
352
366
|
),
|
|
353
367
|
)
|
|
354
|
-
sleep(delay_launch)
|
|
355
368
|
serverapp_th.start()
|
|
356
369
|
return serverapp_th
|
|
357
370
|
|
|
@@ -365,6 +378,8 @@ def _main_loop(
|
|
|
365
378
|
is_app: bool,
|
|
366
379
|
enable_tf_gpu_growth: bool,
|
|
367
380
|
run: Run,
|
|
381
|
+
exit_event: EventType,
|
|
382
|
+
delay_start: int,
|
|
368
383
|
flwr_dir: Optional[str] = None,
|
|
369
384
|
client_app: Optional[ClientApp] = None,
|
|
370
385
|
client_app_attr: Optional[str] = None,
|
|
@@ -372,7 +387,7 @@ def _main_loop(
|
|
|
372
387
|
server_app_attr: Optional[str] = None,
|
|
373
388
|
server_app_run_config: Optional[UserConfig] = None,
|
|
374
389
|
) -> None:
|
|
375
|
-
"""
|
|
390
|
+
"""Start ServerApp on a separate thread, then launch Simulation Engine."""
|
|
376
391
|
# Initialize StateFactory
|
|
377
392
|
state_factory = StateFactory(":flwr-in-memory-state:")
|
|
378
393
|
|
|
@@ -380,6 +395,7 @@ def _main_loop(
|
|
|
380
395
|
# A Threading event to indicate if an exception was raised in the ServerApp thread
|
|
381
396
|
server_app_thread_has_exception = threading.Event()
|
|
382
397
|
serverapp_th = None
|
|
398
|
+
success = True
|
|
383
399
|
try:
|
|
384
400
|
# Register run
|
|
385
401
|
log(DEBUG, "Pre-registering run with id %s", run.run_id)
|
|
@@ -403,8 +419,10 @@ def _main_loop(
|
|
|
403
419
|
enable_tf_gpu_growth=enable_tf_gpu_growth,
|
|
404
420
|
)
|
|
405
421
|
|
|
406
|
-
#
|
|
407
|
-
|
|
422
|
+
# Buffer time so the `ServerApp` in separate thread is ready
|
|
423
|
+
log(DEBUG, "Buffer time delay: %ds", delay_start)
|
|
424
|
+
sleep(delay_start)
|
|
425
|
+
# Start Simulation Engine
|
|
408
426
|
vce.start_vce(
|
|
409
427
|
num_supernodes=num_supernodes,
|
|
410
428
|
client_app_attr=client_app_attr,
|
|
@@ -422,13 +440,13 @@ def _main_loop(
|
|
|
422
440
|
except Exception as ex:
|
|
423
441
|
log(ERROR, "An exception occurred !! %s", ex)
|
|
424
442
|
log(ERROR, traceback.format_exc())
|
|
443
|
+
success = False
|
|
425
444
|
raise RuntimeError("An error was encountered. Ending simulation.") from ex
|
|
426
445
|
|
|
427
446
|
finally:
|
|
428
447
|
# Trigger stop event
|
|
429
448
|
f_stop.set()
|
|
430
|
-
|
|
431
|
-
event(EventType.RUN_SUPERLINK_LEAVE)
|
|
449
|
+
event(exit_event, event_details={"success": success})
|
|
432
450
|
if serverapp_th:
|
|
433
451
|
serverapp_th.join()
|
|
434
452
|
if server_app_thread_has_exception.is_set():
|
|
@@ -440,6 +458,7 @@ def _main_loop(
|
|
|
440
458
|
# pylint: disable=too-many-arguments,too-many-locals
|
|
441
459
|
def _run_simulation(
|
|
442
460
|
num_supernodes: int,
|
|
461
|
+
exit_event: EventType,
|
|
443
462
|
client_app: Optional[ClientApp] = None,
|
|
444
463
|
server_app: Optional[ServerApp] = None,
|
|
445
464
|
backend_name: str = "ray",
|
|
@@ -451,6 +470,7 @@ def _run_simulation(
|
|
|
451
470
|
flwr_dir: Optional[str] = None,
|
|
452
471
|
run: Optional[Run] = None,
|
|
453
472
|
enable_tf_gpu_growth: bool = False,
|
|
473
|
+
delay_start: int = 5,
|
|
454
474
|
verbose_logging: bool = False,
|
|
455
475
|
is_app: bool = False,
|
|
456
476
|
) -> None:
|
|
@@ -506,6 +526,8 @@ def _run_simulation(
|
|
|
506
526
|
is_app,
|
|
507
527
|
enable_tf_gpu_growth,
|
|
508
528
|
run,
|
|
529
|
+
exit_event,
|
|
530
|
+
delay_start,
|
|
509
531
|
flwr_dir,
|
|
510
532
|
client_app,
|
|
511
533
|
client_app_attr,
|
|
@@ -593,6 +615,13 @@ def _parse_args_run_simulation() -> argparse.ArgumentParser:
|
|
|
593
615
|
"Read more about how `tf.config.experimental.set_memory_growth()` works in "
|
|
594
616
|
"the TensorFlow documentation: https://www.tensorflow.org/api/stable.",
|
|
595
617
|
)
|
|
618
|
+
parser.add_argument(
|
|
619
|
+
"--delay-start",
|
|
620
|
+
type=int,
|
|
621
|
+
default=3,
|
|
622
|
+
help="Buffer time (in seconds) to delay the start the simulation engine after "
|
|
623
|
+
"the `ServerApp`, which runs in a separate thread, has been launched.",
|
|
624
|
+
)
|
|
596
625
|
parser.add_argument(
|
|
597
626
|
"--verbose",
|
|
598
627
|
action="store_true",
|
flwr/superexec/__init__.py
CHANGED
flwr/superexec/app.py
CHANGED
|
@@ -56,7 +56,9 @@ def run_superexec() -> None:
|
|
|
56
56
|
address=address,
|
|
57
57
|
executor=_load_executor(args),
|
|
58
58
|
certificates=certificates,
|
|
59
|
-
config=parse_config_args(
|
|
59
|
+
config=parse_config_args(
|
|
60
|
+
[args.executor_config] if args.executor_config else args.executor_config
|
|
61
|
+
),
|
|
60
62
|
)
|
|
61
63
|
|
|
62
64
|
grpc_servers = [superexec_server]
|
{flwr_nightly-1.11.0.dev20240828.dist-info → flwr_nightly-1.11.1.dev20240911.dist-info}/RECORD
RENAMED
|
@@ -6,7 +6,7 @@ flwr/cli/config_utils.py,sha256=mDGXbcIxG14UpkUplILBYUkSk5M1LeTzZYDGNx-pFpU,7540
|
|
|
6
6
|
flwr/cli/example.py,sha256=1bGDYll3BXQY2kRqSN-oICqS5n1b9m0g0RvXTopXHl4,2215
|
|
7
7
|
flwr/cli/install.py,sha256=tUncrbZYRbC9QEcWSeTER16plPEoU-ERP0-nMgWiSPo,7094
|
|
8
8
|
flwr/cli/new/__init__.py,sha256=cQzK1WH4JP2awef1t2UQ2xjl1agVEz9rwutV18SWV1k,789
|
|
9
|
-
flwr/cli/new/new.py,sha256=
|
|
9
|
+
flwr/cli/new/new.py,sha256=9nBm6yjy3q4AHxT-wzV3n5cgO82F19xajfrdu3DIfyk,9605
|
|
10
10
|
flwr/cli/new/templates/__init__.py,sha256=4luU8RL-CK8JJCstQ_ON809W9bNTkY1l9zSaPKBkgwY,725
|
|
11
11
|
flwr/cli/new/templates/app/.gitignore.tpl,sha256=XixnHdyeMB2vwkGtGnwHqoWpH-9WChdyG0GXe57duhc,3078
|
|
12
12
|
flwr/cli/new/templates/app/LICENSE.tpl,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
|
|
@@ -18,13 +18,13 @@ flwr/cli/new/templates/app/code/__init__.baseline.py.tpl,sha256=YkHAgppUeD2BnBoG
|
|
|
18
18
|
flwr/cli/new/templates/app/code/__init__.py,sha256=EM6vfvgAILKPaPn7H1wMV1Wi01WyZCP_Eg6NxD6oWg8,736
|
|
19
19
|
flwr/cli/new/templates/app/code/__init__.py.tpl,sha256=J0Gn74E7khpLyKJVNqOPu7ev93vkcu1PZugsbxtABMw,52
|
|
20
20
|
flwr/cli/new/templates/app/code/client.baseline.py.tpl,sha256=1htktXX3jXX05r0vuG_afjS1sXGtuONW9EpiQ7vSBes,1901
|
|
21
|
-
flwr/cli/new/templates/app/code/client.huggingface.py.tpl,sha256=
|
|
21
|
+
flwr/cli/new/templates/app/code/client.huggingface.py.tpl,sha256=ifD08KwjdoGieV26hFCgf3PQB6rMhj_NZLo5iUUndm8,1846
|
|
22
22
|
flwr/cli/new/templates/app/code/client.jax.py.tpl,sha256=c2LDew2V8BUybZJiz1FeB3Kq4ey0Q2s0S5qNPUTNmI4,1490
|
|
23
23
|
flwr/cli/new/templates/app/code/client.mlx.py.tpl,sha256=gxipt57ldc741qwRqSWtsLQH05JODKdGMTtvoXiBzDA,2906
|
|
24
24
|
flwr/cli/new/templates/app/code/client.numpy.py.tpl,sha256=DMUXvQd2dr-wEn0ZrYJQhZ0OFUT4PKoHXtiD2haWnCI,570
|
|
25
25
|
flwr/cli/new/templates/app/code/client.pytorch.py.tpl,sha256=WczaR5avJUhfw2Grn2KEC4tDJ4voIYG-2pAy-7i2cT8,1685
|
|
26
26
|
flwr/cli/new/templates/app/code/client.sklearn.py.tpl,sha256=xW9cuKhybk5S8IeDZhbeb0DNegDIJGEYrzMKsxgc2GE,2978
|
|
27
|
-
flwr/cli/new/templates/app/code/client.tensorflow.py.tpl,sha256=
|
|
27
|
+
flwr/cli/new/templates/app/code/client.tensorflow.py.tpl,sha256=yBiiU7B9Kf70U52cPkNs_dUpYrrTwbUi2os-PAyheaM,1680
|
|
28
28
|
flwr/cli/new/templates/app/code/dataset.baseline.py.tpl,sha256=jbd_exHAk2-Blu_kVutjPO6a_dkJQWb232zxSeXIZ1k,1453
|
|
29
29
|
flwr/cli/new/templates/app/code/flwr_tune/__init__.py,sha256=JgNgBtKdm1jKM9625WxappCAVUGtYAmcjKSsXJ1u3ZQ,748
|
|
30
30
|
flwr/cli/new/templates/app/code/flwr_tune/client_app.py.tpl,sha256=DbotzaXzLDwplVBkJLOe5Lt5b6Yutwv9rJ69oVwyrvU,4397
|
|
@@ -34,7 +34,7 @@ flwr/cli/new/templates/app/code/flwr_tune/server_app.py.tpl,sha256=yMVcbfGkTPV9A
|
|
|
34
34
|
flwr/cli/new/templates/app/code/flwr_tune/strategy.py.tpl,sha256=BhiqRg9w1MGuU5h2_vrLhRc0oHItYzE69qX_JI411k8,2754
|
|
35
35
|
flwr/cli/new/templates/app/code/model.baseline.py.tpl,sha256=cSz6-IWsnMl7s04DW4URINiIppCIberrtE8NqK6Qz48,2571
|
|
36
36
|
flwr/cli/new/templates/app/code/server.baseline.py.tpl,sha256=outx7lDXsWS8QXKWOGOiDno6eE8WL7LBD51ZkAuC3WU,1570
|
|
37
|
-
flwr/cli/new/templates/app/code/server.huggingface.py.tpl,sha256=
|
|
37
|
+
flwr/cli/new/templates/app/code/server.huggingface.py.tpl,sha256=0PJmnZvR9_VPLSak1yVfkOx3dmqo6cynhY1l2s4AZrE,1158
|
|
38
38
|
flwr/cli/new/templates/app/code/server.jax.py.tpl,sha256=pIdUH-LgWRAGWQYLlivMNf8XnDSNDe2cCuRjlxbRzys,529
|
|
39
39
|
flwr/cli/new/templates/app/code/server.mlx.py.tpl,sha256=RqiZ0k468SOlm9dcPr-fvA8xcWv4zwDCbJfBwL7P9Us,529
|
|
40
40
|
flwr/cli/new/templates/app/code/server.numpy.py.tpl,sha256=RqiZ0k468SOlm9dcPr-fvA8xcWv4zwDCbJfBwL7P9Us,529
|
|
@@ -42,7 +42,7 @@ flwr/cli/new/templates/app/code/server.pytorch.py.tpl,sha256=DW5c8vzXCvFeIE8YIWB
|
|
|
42
42
|
flwr/cli/new/templates/app/code/server.sklearn.py.tpl,sha256=25Ae3kDqjDdBl8LwkDwye69nevd02Pk_e7F3SQKLdyk,624
|
|
43
43
|
flwr/cli/new/templates/app/code/server.tensorflow.py.tpl,sha256=xMhQ7AumowgLkgUilgjVK7IbpRhPjslhVJU-vID6NY8,856
|
|
44
44
|
flwr/cli/new/templates/app/code/strategy.baseline.py.tpl,sha256=YkHAgppUeD2BnBoGfVB6dEvBfjuIPGsU1gw4CiUi3qA,40
|
|
45
|
-
flwr/cli/new/templates/app/code/task.huggingface.py.tpl,sha256=
|
|
45
|
+
flwr/cli/new/templates/app/code/task.huggingface.py.tpl,sha256=ua6cAhJYPUCwML20DEucM0F4ZzzsEVQLYrRvhQ7CGRE,3347
|
|
46
46
|
flwr/cli/new/templates/app/code/task.jax.py.tpl,sha256=F05eg149c9icRyVNdfcLyZvAXROQ7QhfifoGw_U1dsg,1530
|
|
47
47
|
flwr/cli/new/templates/app/code/task.mlx.py.tpl,sha256=jWtCULLRr_9bCIJvoTLMx037-SDl_LF8udtA1UGoXDk,2946
|
|
48
48
|
flwr/cli/new/templates/app/code/task.pytorch.py.tpl,sha256=NgbPix74X1t3ybaGjqdls30vF1i5oY3L7EQExhWhN74,3812
|
|
@@ -50,7 +50,7 @@ flwr/cli/new/templates/app/code/task.tensorflow.py.tpl,sha256=SKXAZdgBnPpbAbJ90R
|
|
|
50
50
|
flwr/cli/new/templates/app/code/utils.baseline.py.tpl,sha256=YkHAgppUeD2BnBoGfVB6dEvBfjuIPGsU1gw4CiUi3qA,40
|
|
51
51
|
flwr/cli/new/templates/app/pyproject.baseline.toml.tpl,sha256=4gi90W9_B1kj6rYkpvVJxhNX9Yctsv9OH6CzXP-dcE4,2666
|
|
52
52
|
flwr/cli/new/templates/app/pyproject.flowertune.toml.tpl,sha256=pogRZLrwSfN_XH4NxDdMkhMh1O_7DP90VOoP-cP0HvI,1827
|
|
53
|
-
flwr/cli/new/templates/app/pyproject.huggingface.toml.tpl,sha256=
|
|
53
|
+
flwr/cli/new/templates/app/pyproject.huggingface.toml.tpl,sha256=CHJgkPNkJfzJhEbTe15uiV3AhOtIddQi-yofPZsCk3E,1143
|
|
54
54
|
flwr/cli/new/templates/app/pyproject.jax.toml.tpl,sha256=Tq6jeGcoOKzMwWWYxMVnzMcipLURHLiW69iYlD1ywMg,659
|
|
55
55
|
flwr/cli/new/templates/app/pyproject.mlx.toml.tpl,sha256=SHwYAA2qgIlOAU3Sb9BKSZcZ7O9biACg27MHexXUtDw,741
|
|
56
56
|
flwr/cli/new/templates/app/pyproject.numpy.toml.tpl,sha256=-FCi64ygMgQke3zApUt0XtkIBo3WtQoPAPhtp_FqkPE,612
|
|
@@ -60,10 +60,10 @@ flwr/cli/new/templates/app/pyproject.tensorflow.toml.tpl,sha256=bRIvPCPvTTI4Eo5b
|
|
|
60
60
|
flwr/cli/run/__init__.py,sha256=oCd6HmQDx-sqver1gecgx-uMA38BLTSiiKpl7RGNceg,789
|
|
61
61
|
flwr/cli/run/run.py,sha256=RI6MgLBNYxmacjQg8XMAQ7VKxbV0DkRyJTfe4GsDFuw,7979
|
|
62
62
|
flwr/cli/utils.py,sha256=l65Ul0YsSBPuypk0uorAtEDmLEYiUrzpCXi6zCg9mJ4,4506
|
|
63
|
-
flwr/client/__init__.py,sha256=
|
|
63
|
+
flwr/client/__init__.py,sha256=DGDoO0AEAfz-0CUFmLdyUUweAS64-07AOnmDfWUefK4,1192
|
|
64
64
|
flwr/client/app.py,sha256=o_2bhmlBeZATtWnAPZhL-Q1Ly0QZxc9ou4i7t0HKumE,31956
|
|
65
65
|
flwr/client/client.py,sha256=gy6WVlMUFAp8oevN4xpQPX30vPOIYGVqdbuFlTWkyG4,9080
|
|
66
|
-
flwr/client/client_app.py,sha256=
|
|
66
|
+
flwr/client/client_app.py,sha256=6TIH-B5lgKn199uzcjxfFKiGvKN5tmKYFpsovUrSXoo,10396
|
|
67
67
|
flwr/client/clientapp/__init__.py,sha256=kZqChGnTChQ1WGSUkIlW2S5bc0d0mzDubCAmZUGRpEY,800
|
|
68
68
|
flwr/client/clientapp/app.py,sha256=4QtblvJsZ0-V-QBbzyNqWV13ugrgJmkZnsHpBCuqgi8,7797
|
|
69
69
|
flwr/client/clientapp/clientappio_servicer.py,sha256=5L6bjw_j3Mnx9kRFwYwxDNABKurBO5q1jZOWE_X11wQ,8522
|
|
@@ -74,7 +74,7 @@ flwr/client/grpc_adapter_client/connection.py,sha256=aOlCYasl8f2CrfcN-WrVEmvjAZF
|
|
|
74
74
|
flwr/client/grpc_client/__init__.py,sha256=LsnbqXiJhgQcB0XzAlUQgPx011Uf7Y7yabIC1HxivJ8,735
|
|
75
75
|
flwr/client/grpc_client/connection.py,sha256=czhRm23fwTgjN24Vf5nyNQ3hcb5Fo_5k-o9yZnelQCs,9362
|
|
76
76
|
flwr/client/grpc_rere_client/__init__.py,sha256=MK-oSoV3kwUEQnIwl0GN4OpiHR7eLOrMA8ikunET130,752
|
|
77
|
-
flwr/client/grpc_rere_client/client_interceptor.py,sha256=
|
|
77
|
+
flwr/client/grpc_rere_client/client_interceptor.py,sha256=eONCq-uRYvRCxjdP4wIi_FDynDipHs3DYjExgzAcJ5M,5240
|
|
78
78
|
flwr/client/grpc_rere_client/connection.py,sha256=aiIWW9fVgJZNeZ9SjUAx5ax-3825JrjYc5E5l7XvzyM,10913
|
|
79
79
|
flwr/client/grpc_rere_client/grpc_adapter.py,sha256=Pw7Toi4wCUIEdBMyv4yKirjgW6814gFhhAmsTYmV4IM,5005
|
|
80
80
|
flwr/client/heartbeat.py,sha256=cx37mJBH8LyoIN4Lks85wtqT1mnU5GulQnr4pGCvAq0,2404
|
|
@@ -118,8 +118,8 @@ flwr/common/record/configsrecord.py,sha256=6nIpGaeB_o8SvjMfD_iehJC1efAHgWyaeGfLD
|
|
|
118
118
|
flwr/common/record/conversion_utils.py,sha256=n3I3SI2P6hUjyxbWNc0QAch-SEhfMK6Hm-UUaplAlUc,1393
|
|
119
119
|
flwr/common/record/metricsrecord.py,sha256=aTuw0gWjRaZhekf76zg0h0rES3iEnTIGPZ7-jN2PYO4,5764
|
|
120
120
|
flwr/common/record/parametersrecord.py,sha256=mOcERCUylgWLQ-hISYmOHXlt-Qohv8YtPnJdLO0Kr8U,7730
|
|
121
|
-
flwr/common/record/recordset.py,sha256=
|
|
122
|
-
flwr/common/record/typeddict.py,sha256=
|
|
121
|
+
flwr/common/record/recordset.py,sha256=sSofrBycZSqiHR4TzfI4_QoIIN-5B1LnMG0C9CiByAo,8312
|
|
122
|
+
flwr/common/record/typeddict.py,sha256=TDPLdeuHiAUy9JyfJN0VF1zSyqdnf_uNWUFjAd2z_Os,3623
|
|
123
123
|
flwr/common/recordset_compat.py,sha256=5prvfx8mT4ZWIEU4Gmz2wzCbO4yPjQ3ONr20uKt3UM0,13973
|
|
124
124
|
flwr/common/retry_invoker.py,sha256=dQY5fPIKhy9OiFswZhLxA9fB455u-DYCvDVcFJmrPDk,11707
|
|
125
125
|
flwr/common/secure_aggregation/__init__.py,sha256=erPnTWdOfMH0K0HQTmj5foDJ6t3iYcExy2aACy8iZNQ,731
|
|
@@ -131,7 +131,7 @@ flwr/common/secure_aggregation/quantization.py,sha256=1obYr9qneaI8r-A0F_pghrPNG9
|
|
|
131
131
|
flwr/common/secure_aggregation/secaggplus_constants.py,sha256=9MF-oQh62uD7rt9VeNB-rHf2gBLd5GL3S9OejCxmILY,2183
|
|
132
132
|
flwr/common/secure_aggregation/secaggplus_utils.py,sha256=3VssKgYF7HQIkSpROnEUoYWVt47p12PE_Rj4nYqqg04,3221
|
|
133
133
|
flwr/common/serde.py,sha256=SIKZa-TNCSWVtqx8L3aUkylN6gxK-IwXlgoukiYwYyc,29209
|
|
134
|
-
flwr/common/telemetry.py,sha256=
|
|
134
|
+
flwr/common/telemetry.py,sha256=CZeBHqaH_W-H7yo-9LE-gV7ju5gJTXZztw4tJlFZqz8,8916
|
|
135
135
|
flwr/common/typing.py,sha256=rGabiSkjFvGIHwmhDqtuu-LBvz7LVSj1vyMlNtA7VA0,5004
|
|
136
136
|
flwr/common/version.py,sha256=W1ntylR04xkCP6zeSet6sRtBn7P1cje2lOqBJgYBjJY,1349
|
|
137
137
|
flwr/proto/__init__.py,sha256=hbY7JYakwZwCkYgCNlmHdc8rtvfoJbAZLalMdc--CGc,683
|
|
@@ -192,19 +192,19 @@ flwr/proto/transport_pb2.pyi,sha256=CZvJRWTU3QWFWLXNFtyLSrSKFatIyMcy-ohzLbQ-G9c,
|
|
|
192
192
|
flwr/proto/transport_pb2_grpc.py,sha256=vLN3EHtx2aEEMCO4f1Upu-l27BPzd3-5pV-u8wPcosk,2598
|
|
193
193
|
flwr/proto/transport_pb2_grpc.pyi,sha256=AGXf8RiIiW2J5IKMlm_3qT3AzcDa4F3P5IqUjve_esA,766
|
|
194
194
|
flwr/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
195
|
-
flwr/server/__init__.py,sha256=
|
|
195
|
+
flwr/server/__init__.py,sha256=cEg1oecBu4cKB69iJCqWEylC8b5XW47bl7rQiJsdTvM,1528
|
|
196
196
|
flwr/server/app.py,sha256=QFnqrN1aeNTN-hmHt2YcqZNncAq89Qr2mlZtwITRIc4,24430
|
|
197
197
|
flwr/server/client_manager.py,sha256=T8UDSRJBVD3fyIDI7NTAA-NA7GPrMNNgH2OAF54RRxE,6127
|
|
198
198
|
flwr/server/client_proxy.py,sha256=4G-oTwhb45sfWLx2uZdcXD98IZwdTS6F88xe3akCdUg,2399
|
|
199
199
|
flwr/server/compat/__init__.py,sha256=VxnJtJyOjNFQXMNi9hIuzNlZM5n0Hj1p3aq_Pm2udw4,892
|
|
200
|
-
flwr/server/compat/app.py,sha256=
|
|
200
|
+
flwr/server/compat/app.py,sha256=5vkHHm_h-4cMthvWD1GJo1ZW3eihytjGgvsgfXUK9gA,3298
|
|
201
201
|
flwr/server/compat/app_utils.py,sha256=B9pec7LnYACzowXKZTZNu3SNS-fSaHfefwvRyAQa4Nc,3456
|
|
202
202
|
flwr/server/compat/driver_client_proxy.py,sha256=BxTDo7i89VAG2tuF4x7zogSVn2bXPMr0H2H0lERzW9c,5444
|
|
203
203
|
flwr/server/compat/legacy_context.py,sha256=wBzBcfV6YO6IQGriM_FdJ5XZfiBBEEJdS_OdAiF47dY,1804
|
|
204
204
|
flwr/server/criterion.py,sha256=ypbAexbztzGUxNen9RCHF91QeqiEQix4t4Ih3E-42MM,1061
|
|
205
205
|
flwr/server/driver/__init__.py,sha256=bikRv6CjTwSvYh7tf10gziU5o2YotOWhhftz2tr3KDc,886
|
|
206
206
|
flwr/server/driver/driver.py,sha256=NT_yaeit7_kZEIsCEqOWPID1GrVD3ywH4xZ2wtIh5lM,5217
|
|
207
|
-
flwr/server/driver/grpc_driver.py,sha256=
|
|
207
|
+
flwr/server/driver/grpc_driver.py,sha256=qrCF0hi2AlKF_8R5N_W5aKoAxd80lN1xbdLTUVtpSO0,9648
|
|
208
208
|
flwr/server/driver/inmemory_driver.py,sha256=RcK94_NtjGZ4aZDIscnU7A3Uv1u8jGx29-xcbjQvZTM,6444
|
|
209
209
|
flwr/server/history.py,sha256=bBOHKyX1eQONIsUx4EUU-UnAk1i0EbEl8ioyMq_UWQ8,5063
|
|
210
210
|
flwr/server/run_serverapp.py,sha256=Xw42zqNXmKGy3Fz5QjYOUS1MH7ULy2u9nad4QA8hh74,10479
|
|
@@ -254,7 +254,7 @@ flwr/server/superlink/fleet/grpc_bidi/grpc_client_proxy.py,sha256=h3EhqgelegVC4E
|
|
|
254
254
|
flwr/server/superlink/fleet/grpc_bidi/grpc_server.py,sha256=DIXCYfPwm5paWq6hccReW0tB7-dTfq4vvMZ7CsiuYf4,12292
|
|
255
255
|
flwr/server/superlink/fleet/grpc_rere/__init__.py,sha256=j2hyC342am-_Hgp1g80Y3fGDzfTI6n8QOOn2PyWf4eg,758
|
|
256
256
|
flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py,sha256=bgoLQEhahVHjdlRDk_58zyKFeMOziiPUXSbYMhOxybY,4757
|
|
257
|
-
flwr/server/superlink/fleet/grpc_rere/server_interceptor.py,sha256=
|
|
257
|
+
flwr/server/superlink/fleet/grpc_rere/server_interceptor.py,sha256=zN8TIdg9ZxKtmrwtarWUPdm08jUBBGoz59ndO3C-7jg,7985
|
|
258
258
|
flwr/server/superlink/fleet/message_handler/__init__.py,sha256=h8oLD7uo5lKICPy0rRdKRjTYe62u8PKkT_fA4xF5JPA,731
|
|
259
259
|
flwr/server/superlink/fleet/message_handler/message_handler.py,sha256=9qDDPwj3txHPo2dNaWQiO3UpGno5Zm9IMhJXnAPZbqg,4439
|
|
260
260
|
flwr/server/superlink/fleet/rest_rere/__init__.py,sha256=5jbYbAn75sGv-gBwOPDySE0kz96F6dTYLeMrGqNi4lM,735
|
|
@@ -262,7 +262,7 @@ flwr/server/superlink/fleet/rest_rere/rest_api.py,sha256=3wegOVJadA3pH_2CwZHQ3Uw
|
|
|
262
262
|
flwr/server/superlink/fleet/vce/__init__.py,sha256=36MHKiefnJeyjwMQzVUK4m06Ojon3WDcwZGQsAcyVhQ,783
|
|
263
263
|
flwr/server/superlink/fleet/vce/backend/__init__.py,sha256=psQjI1DQHOM5uWVXM27l_wPHjfEkMUTP-_8-lEFH1JA,1466
|
|
264
264
|
flwr/server/superlink/fleet/vce/backend/backend.py,sha256=YugFH_XYclqmq07er5ne1DZc7PgR9lWGs5LY_YIHwc8,2207
|
|
265
|
-
flwr/server/superlink/fleet/vce/backend/raybackend.py,sha256=
|
|
265
|
+
flwr/server/superlink/fleet/vce/backend/raybackend.py,sha256=VQ63rZytcavfDedfjArAejPi3VGYXrfcsb8yi57prRc,7168
|
|
266
266
|
flwr/server/superlink/fleet/vce/vce_api.py,sha256=lTQ2WycKK4-w22EPoJJz1qn73j9ZTwBlNz2cla2Zv0Q,12653
|
|
267
267
|
flwr/server/superlink/state/__init__.py,sha256=Gj2OTFLXvA-mAjBvwuKDM3rDrVaQPcIoybSa2uskMTE,1003
|
|
268
268
|
flwr/server/superlink/state/in_memory_state.py,sha256=eNXOVt3HhJOYxkbYRNWEudCaNrYj2B7tOU9xgKbM2Ag,13166
|
|
@@ -283,19 +283,19 @@ flwr/server/workflow/secure_aggregation/secaggplus_workflow.py,sha256=vdS_AeRYBv
|
|
|
283
283
|
flwr/simulation/__init__.py,sha256=ybVBW3xT6cg_IasJV4_ymI3bVrCbFhw1mmcfrdfl3q0,1359
|
|
284
284
|
flwr/simulation/app.py,sha256=te3dQB3eodPwzsv1y4daPyaskIAaOtgoHaQLobrqoqY,15163
|
|
285
285
|
flwr/simulation/ray_transport/__init__.py,sha256=wzcEEwUUlulnXsg6raCA1nGpP3LlAQDtJ8zNkCXcVbA,734
|
|
286
|
-
flwr/simulation/ray_transport/ray_actor.py,sha256=
|
|
286
|
+
flwr/simulation/ray_transport/ray_actor.py,sha256=IbFwbRFxKHoLjgx_LTuehS0L3uHPw_SPaMfA4wHA0Xk,19026
|
|
287
287
|
flwr/simulation/ray_transport/ray_client_proxy.py,sha256=0abIsU0VBk9rNJZOKHIyzYGy3ZnWBgqYocX_oct1EP0,7307
|
|
288
288
|
flwr/simulation/ray_transport/utils.py,sha256=TYdtfg1P9VfTdLMOJlifInGpxWHYs9UfUqIv2wfkRLA,2392
|
|
289
|
-
flwr/simulation/run_simulation.py,sha256=
|
|
290
|
-
flwr/superexec/__init__.py,sha256=
|
|
291
|
-
flwr/superexec/app.py,sha256=
|
|
289
|
+
flwr/simulation/run_simulation.py,sha256=hnH3qThfg_ii2tMu1y3X4ZWbw99CNk7vfduQ1fdZxbY,22750
|
|
290
|
+
flwr/superexec/__init__.py,sha256=fcj366jh4RFby_vDwLroU4kepzqbnJgseZD_jUr_Mko,715
|
|
291
|
+
flwr/superexec/app.py,sha256=gH25dr7FL9IWODSOtP0-r59iuOKDeSXLLPxpEAL50BM,6561
|
|
292
292
|
flwr/superexec/deployment.py,sha256=1qhztkcZDjaSbicligbXGqn49gbpN271rTlEVAnNuWw,6283
|
|
293
293
|
flwr/superexec/exec_grpc.py,sha256=PhqGoZEpTMxSQmUSV8Wgtzb1Za_pHJ-adZqo5RYnDyE,1942
|
|
294
294
|
flwr/superexec/exec_servicer.py,sha256=jl0aKVjm0PLQABcTL5c3jdSIzb0Z6hpVOtrAn4Ob7ts,2323
|
|
295
295
|
flwr/superexec/executor.py,sha256=k_adivto6R2U82DADOHNvdtobehBYreRek1gOEBIQnQ,2318
|
|
296
296
|
flwr/superexec/simulation.py,sha256=J6pw-RqCSiUed8I_3MasZH4tl57ZmDebPAHNnbb0-vE,7420
|
|
297
|
-
flwr_nightly-1.11.
|
|
298
|
-
flwr_nightly-1.11.
|
|
299
|
-
flwr_nightly-1.11.
|
|
300
|
-
flwr_nightly-1.11.
|
|
301
|
-
flwr_nightly-1.11.
|
|
297
|
+
flwr_nightly-1.11.1.dev20240911.dist-info/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
|
|
298
|
+
flwr_nightly-1.11.1.dev20240911.dist-info/METADATA,sha256=96wpiwqS16Lsmrnng5_AdtynkNwGP4BsjBY0jRwKYYk,15703
|
|
299
|
+
flwr_nightly-1.11.1.dev20240911.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
|
|
300
|
+
flwr_nightly-1.11.1.dev20240911.dist-info/entry_points.txt,sha256=WUCbqhLEOzjx_lyATIM0-f0e8kOVaQjzwOvyOxHrMhs,434
|
|
301
|
+
flwr_nightly-1.11.1.dev20240911.dist-info/RECORD,,
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
[console_scripts]
|
|
2
|
+
flower-client-app=flwr.client.supernode:run_client_app
|
|
3
|
+
flower-server-app=flwr.server.run_serverapp:run_server_app
|
|
4
|
+
flower-simulation=flwr.simulation.run_simulation:run_simulation_from_cli
|
|
5
|
+
flower-superexec=flwr.superexec.app:run_superexec
|
|
6
|
+
flower-superlink=flwr.server.app:run_superlink
|
|
7
|
+
flower-supernode=flwr.client.supernode.app:run_supernode
|
|
8
|
+
flwr=flwr.cli.app:app
|
|
9
|
+
flwr-clientapp=flwr.client.clientapp:flwr_clientapp
|
|
10
|
+
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
[console_scripts]
|
|
2
|
-
flower-client-app=flwr.client:run_client_app
|
|
3
|
-
flower-server-app=flwr.server:run_server_app
|
|
4
|
-
flower-simulation=flwr.simulation.run_simulation:run_simulation_from_cli
|
|
5
|
-
flower-superexec=flwr.superexec:run_superexec
|
|
6
|
-
flower-superlink=flwr.server:run_superlink
|
|
7
|
-
flower-supernode=flwr.client:run_supernode
|
|
8
|
-
flwr=flwr.cli.app:app
|
|
9
|
-
flwr-clientapp=flwr.client.clientapp:flwr_clientapp
|
|
10
|
-
|
{flwr_nightly-1.11.0.dev20240828.dist-info → flwr_nightly-1.11.1.dev20240911.dist-info}/LICENSE
RENAMED
|
File without changes
|
{flwr_nightly-1.11.0.dev20240828.dist-info → flwr_nightly-1.11.1.dev20240911.dist-info}/WHEEL
RENAMED
|
File without changes
|