Executor¶
An Executor
is an FLComponent for FL clients used for executing tasks,
wherein the execute
method receives and returns a Shareable object given a task name,
FLContext
, and abort_signal
.
class Executor(FLComponent, ABC):
"""Executors run on federated client side.
Each job can contain multiple applications or apps folder.
Each site (server or client) will have 1 app deployed for that job.
The server side app contains a Controller that will schedule `Task`.
The client side app contains an Executor that will execute corresponding logic based on `Task`'s name.
"""
def __init__(self):
FLComponent.__init__(self)
self.unsafe = False
@abstractmethod
def execute(self, task_name: str, shareable: Shareable, fl_ctx: FLContext, abort_signal: Signal) -> Shareable:
"""Executes a task.
Args:
task_name (str): task name.
shareable (Shareable): input shareable.
fl_ctx (FLContext): fl context.
abort_signal (Signal): signal to check during execution to determine whether this task is aborted.
Returns:
An output shareable.
"""
pass
def get_job_target_type(self):
"""This method is used by Job API.
Returns:
"""
return JobTargetType.CLIENT
def add_to_fed_job(self, job, ctx, **kwargs):
"""This method is used by Job API.
Args:
job: the Job object to add to
ctx: Job Context
Returns:
"""
job.check_kwargs(args_to_check=kwargs, args_expected={"tasks": False})
tasks = kwargs.get("tasks", ["*"])
job.add_executor(obj=self, tasks=tasks, ctx=ctx)
Examples for Executors are Trainer
and Validator
.
The source code for some example implementations can be found in the example apps. On clients, tasks can be configured
for Executors in config_fed_client.json:
{
"format_version": 2,
"handlers": [],
"executors": [
{
"tasks": [
"train",
"submit_model"
],
"executor": {
"path": "np_trainer.NPTrainer",
"args": {}
}
},
{
"tasks": [
"validate"
],
"executor": {
"path": "np_validator.NPValidator"
}
}
],
"task_result_filters": [],
"task_data_filters": [],
"components": []
}
The above configuration is an example from hello_numpy. Each task can only be assigned to one Executor.
Multi-Process Executor¶
MultiProcessExecutor
is designed to
easily allow the FL executor to support multi-processes execution. The behavior of the Executor remains the same
including the firing and handling of FL events. MultiProcessExecutor allows researchers to focus on the training and
execution logic instead of worrying about how to make use of multiple processes or deal with multi-GPU training.
During the execution, any event fired from other components will be relayed from the MultiProcessExecutor to all the sub-worker processes. Any component which listens to the event in the sub-worker processes can handle the event accordingly. Also, any event fired by the FL component in the sub-worker processes will be relayed by the MultiProcessExecutor to all other components to handle.
MultiProcessExecutor keeps the same FL Executor API signature. When turning the FL executor into MultiProcessExecutor, configure the task executor to use MultiProcessExecutor (currently PTMultiProcessExecutor is the only implemented MultiProcessExecutor), and configure the existing executor as the “executor_id”, and the number of processes to use.
{
"executors": [
{
"tasks": [
"train"
],
"executor": {
"path": "nvflare.app_common.pt.pt_multi_process_executor.PTMultiProcessExecutor",
"args": {
"executor_id": "trainer",
"num_of_processes": 2,
"components": [
{
"id": "trainer",
"path": "medl.apps.fed_learn.trainers.client_trainer.ClientTrainer",
"args": {
"local_epochs": 5,
"steps_aggregation": 0,
"model_reader_writer": {
"path": "nvflare.app_opt.pt.model_reader_writer.PTModelReaderWriter"
}
}
}
]
}
}
}
],
}