Skip to content

Unreliable Client Connectivity

Unreliable client connectivity means the server may lose connections accidiently to the selected clients. Therefore, the server cannot expect to successfully received the locally updated model from the dropped clinets. To model the unreliable client connectivity, FLGo allocates each client a probability of dropping out after it was selected. The probability can be timely changed by the Simulator. Now we provide examples to show how to set the dropping probability of clients.

To update clients' connectivity, set the prob_drop by method set_variable(client_ids: List[int], var_name:str='prob_drop'', )

Example

import numpy as np
import flgo.simulator.base
import flgo
# 1. let the probability of dropping out of each client obey UNIFORM(0,0.5) at each round
class CONSimulator(flgo.simulator.base.BasicSimulator):
    def update_client_connectivity(self, client_ids):
        self.set_variable(client_ids, 'prob_drop', np.random.uniform(0.,0.5, len(client_ids)).tolist())

# 2. generate task
task = './DIR_cifar10'
gen_config = {
    'benchmark': cifar,
    'partitioner': fbp.DirichletPartitioner
}
if not os.path.exists(task): flgo.gen_task(gen_config, task_path=task)

# 3. Log the time cost
import flgo.experiment.logger as fel
class MyLogger(fel.BasicLogger):
    def log_once(self, *args, **kwargs):
        self.info('Current_time:{}'.format(self.clock.current_time))
        super(MyLogger, self).log_once()
        self.output['time'].append(self.clock.current_time)

if __name__ == '__main__':
    # 4. set the time waiting for dropped clients to be 10 units by `set_tolerance_for_latency`
    # remark: the undropped clients will immediately return the locally trained model ideally
    # Specify Logger and Simulator respectively by their keywords
    import flgo.algorithm.fedavg as fedavg
    runner_fedavg = flgo.init(task, fedavg, {'gpu':[0,],'log_file':True, 'num_epochs':1, 'num_rounds':20}, Logger=MyLogger)
    runner_fedavg.set_tolerance_for_latency(10)
    runner_fedavg.run()

    runner_fedavg_with_drop = flgo.init(task, fedavg, {'gpu':[0,],'log_file':True, 'num_epochs':1, 'num_rounds':20}, Logger=MyLogger, Simulator=CONSimulator)
    runner_fedavg_with_drop.set_tolerance_for_latency(10)
    runner_fedavg_with_drop.run()

    # 5. Visualize Acc. v.s. Rounds\Time
    import flgo.experiment.analyzer
    analysis_plan = {
        'Selector': {'task': task, 'header':['fedavg',] ,'legend_with':['SIM']},
        'Painter': {
            'Curve': [
                {
                    'args': {'x': 'communication_round', 'y': 'test_accuracy'},
                    'obj_option': {'color': ['r', 'g', 'b', 'y', 'skyblue']},
                    'fig_option': {'xlabel': 'communication round', 'ylabel': 'test_accuracy',
                                   'title': 'fedavg on {}'.format(task)}
                },
                {
                    'args': {'x': 'time', 'y': 'test_accuracy'},
                    'obj_option': {'color': ['r', 'g', 'b', 'y', 'skyblue']},
                    'fig_option': {'xlabel': 'time', 'ylabel': 'test_accuracy',
                                   'title': 'fedavg on {}'.format(task)}
                },
            ]
        },
    }
    flgo.experiment.analyzer.show(analysis_plan)

The results indicate that useless waiting of the server will cause time wasting. fig-con