-
Notifications
You must be signed in to change notification settings - Fork 210
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Straggler handling Follow-up #1097
base: develop
Are you sure you want to change the base?
Straggler handling Follow-up #1097
Conversation
Signed-off-by: Ishant Thakare <[email protected]>
Signed-off-by: Ishant Thakare <[email protected]>
@ishant162 , did you test for regression by raising a PR in OpenFL-Security? |
This needs to be done @teoparvanov . We will feedback once it is done |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a good improvement over the previous layout.
Most suggestions, though seem like nitpicks, have measurable changes on developers and users in the look-and-feel of the framework. Please take a look.
@@ -69,7 +69,7 @@ def __init__( | |||
best_state_path, | |||
last_state_path, | |||
assigner, | |||
straggler_handling_policy=None, | |||
straggler_handling_policy=CutoffPolicy, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a typehint.
straggler_handling_policy: BasePolicy = CutoffPolicy,
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Accepted. Will incorpoate
@@ -92,7 +92,7 @@ def __init__( | |||
weight. | |||
assigner: Assigner object. | |||
straggler_handling_policy (optional): Straggler handling policy. | |||
Defaults to CutoffTimeBasedStragglerHandling. | |||
Defaults to CutoffPolicy. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggest removing the mention of default. Most IDEs show this when defaults are provided. One less line to maintain if default changes in the future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Accepted. Will incorpoate
if straggler_handling_policy == CutoffPolicy: | ||
self.straggler_handling_policy = straggler_handling_policy() | ||
else: | ||
self.straggler_handling_policy = straggler_handling_policy | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest creating a DefaultPolicy
. This simplifies:
self.straggler_handling_policy = straggler_handling_policy()
regardless of what is given, saves 4 lines.DefaultPolicy
would be the equivalent of providing no straggler handling capabilities. Dummy class.
Also the condition check is wrong. What if PercentagePolicy
is provided? It will go to else block and fail in code, it seems.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Incorporated the suggestion you provided.
def start_policy(self, **kwargs) -> None: | ||
""" | ||
Start straggler handling policy for collaborator for a particular round. | ||
NOTE: Refer CutoffPolicy for reference. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is CutoffPolicy
mentioned here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To showcase the CutoffPolicy's
start_policy
implementation as a reference for users.
""" | ||
Reset policy variable for the next round. | ||
|
||
Args: | ||
None | ||
|
||
Returns: | ||
None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this is the case for subclassed policies, please eliminate empty lines. It suffices to say Resets policy for the next round
and not using 6 lines to say it takes or returns nothing. The -> None
and no args make it obvious to the user in an IDE.
Also on the info itself: It is better to mention what exactly is being reset without leaking into the detail. Example Resets countdown timer for collaborator reporting until next round
, or along those lines.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Accepted. Will incorpoate
"""Initialize a PercentagePolicy object. | ||
|
||
Args: | ||
percent_collaborators_needed (float, optional): The percentage of | ||
collaborators needed. Defaults to 1.0. | ||
minimum_reporting (int, optional): The minimum number of | ||
collaborators that should report. Defaults to 1. | ||
**kwargs: Variable length argument list. | ||
""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Class docstring should go near attributes, not in __init__
. Example:
class PercentagePolicy(StragglerHandlingPolicy):
"""Percentage based Straggler Handling function.
Args:
percent_collaborators_needed (float, optional): The percentage of
collaborators required before concluding the round. Defaults to 1.0.
minimum_reporting (int, optional): The minimum number of
collaborators that should report, regardless of percentage threshold. Defaults to 1.
**kwargs: Variable length argument list.
"""
def __init__(self, percent_collaborators_needed=1.0, minimum_reporting=1, **kwargs):
if minimum_reporting <= 0:
raise ValueError("minimum_reporting must be >0")
self.percent_collaborators_needed = percent_collaborators_needed
self.minimum_reporting = minimum_reporting
self.logger = getLogger(__name__)
On the **kwargs
: Why would a user provide this? Where does it get used, please mention like keyword arguments forwarded to some.module.class
). If they are never forwarded or stored (which seems to be the case looking at certain classes, they should not be accepted from the user either.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The arguments specified are intended for the constructor rather than the class attributes, so they are correctly placed. I have removed the kwargs as per your suggestion.
if minimum_reporting <= 0: | ||
raise ValueError("minimum_reporting must be >0") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One liner: assert minimum_reporting > 0, "Minimum reporting must be >0"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO, assert statements are primarily intended for debugging purposes.
Using raise with a ValueError more clearly indicates that the error is due to an invalid argument
|
||
self.percent_collaborators_needed = percent_collaborators_needed | ||
self.minimum_reporting = minimum_reporting | ||
self.logger = getLogger(__name__) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we start defining logger = getLogger(__name__)
below imports and use it globally within this file?
We should slowly move away from these tiny design choices.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Accepted. Will incorporate
""" | ||
Not required in PercentagePolicy. | ||
""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Save lines!
def reset_policy_for_round(self) -> None:
"""Ignored in `PercentagePolicy`."""
pass
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Accepted. Will incorporate
@@ -421,7 +421,7 @@ def get_tensor_pipe(self): | |||
|
|||
def get_straggler_handling_policy(self): | |||
"""Get straggler handling policy.""" | |||
template = "openfl.component.straggler_handling_functions.CutoffTimeBasedStragglerHandling" | |||
template = "openfl.component.aggregator.straggler_handling.CutoffPolicy" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this default? What is the default behavior?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. In case no policy is specified in plan then straggler handling policy is disabled.
Signed-off-by: Ishant Thakare <[email protected]>
Signed-off-by: Ishant Thakare <[email protected]>
Signed-off-by: Ishant Thakare <[email protected]>
This pull request is a follow-up to the Straggler Handling PR #996 . Based on the feedback from @MasterSkepticista and @teoparvanov , the review comments have been addressed and incorporated accordingly.
Summary of changes:
Relocated straggler_handling to the
openfl/component/aggregator
directory.Consolidated all policies into
openfl/component/aggregator/straggler_handling.py
Renamed
CutoffTimeBasedStragglerHandling
toCutoffPolicy
andPercentageBasedStragglerHandling
toPercentagePolicy
Removed the attribute deletion functionality from
CutoffPolicy
Validate OpenFL Security through regression testing
PR is currently in draft