-
Notifications
You must be signed in to change notification settings - Fork 20
Add iteration counts to MPP protocol #378
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
base: develop
Are you sure you want to change the base?
Changes from 49 commits
e408db5
57373fc
6b4f7ec
5b96e98
0f00d7a
6828544
21f1f65
d40820a
db83a19
0805fdb
7eccccc
cb05529
95ecdf8
60c7942
7851b5a
0464c5f
365ea81
6fb10c4
7d97ab8
1d80efb
77d9f11
d4ccb13
f50f5b7
8eaf5fb
1e23176
196e07d
f11bc85
3b42b2f
ecda1fe
7ba205e
9a41cc0
978c63e
8c56a21
bec712d
bc3167c
f101c3c
1103336
40520af
1729261
ea87146
1a99220
de3876b
9170e9a
d12bc62
a00516a
28c6c52
d0edb55
4f4cf6b
6308361
218ccf8
ecac490
82819cd
2307393
82a8b69
7958461
7a62fdb
72e3628
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,6 +14,7 @@ | |
| from libmuscle.profiler import Profiler | ||
| from libmuscle.profiling import ProfileEvent, ProfileEventType, ProfileTimestamp | ||
| from libmuscle.receive_timeout_handler import Deadlock, ReceiveTimeoutHandler | ||
| from libmuscle.timeline_manager import TimelineManager | ||
|
|
||
| _logger = logging.getLogger(__name__) | ||
|
|
||
|
|
@@ -108,6 +109,8 @@ def __init__( | |
| # indexed by remote instance id | ||
| self._clients: dict[Reference, MPPClient] = {} | ||
|
|
||
| self._timeline_manager = TimelineManager(port_manager) | ||
|
|
||
| def get_locations(self) -> list[str]: | ||
| """Returns a list of locations that we can be reached at. | ||
|
|
||
|
|
@@ -124,12 +127,14 @@ def set_peer_info(self, peer_info: PeerInfo) -> None: | |
| """Inform this Communicator about its peers. | ||
|
|
||
| This tells the Communicator about its peers, so that it can route | ||
| messages accordingly. | ||
| messages accordingly. This also completes the TimelineManager's | ||
| initialization. | ||
|
|
||
| Args: | ||
| peer_info: Information about the peers. | ||
| """ | ||
| self._peer_info = peer_info | ||
| self._timeline_manager.connect_sub_timelines() | ||
|
|
||
| def set_receive_timeout(self, receive_timeout: float) -> None: | ||
| """Update the timeout after which the manager is notified that we are waiting | ||
|
|
@@ -172,6 +177,11 @@ def send_message( | |
| # log sending on disconnected port | ||
| return | ||
|
|
||
| if isinstance(message.data, ClosePort): | ||
| iteration = None | ||
| else: | ||
| iteration = self._timeline_manager.check_send_message(port_name, slot) | ||
|
IrisvdWerf marked this conversation as resolved.
|
||
|
|
||
| port = self._port_manager.get_port(port_name) | ||
| profile_event = ProfileEvent( | ||
| ProfileEventType.SEND, | ||
|
|
@@ -204,6 +214,7 @@ def send_message( | |
| port.get_num_messages(slot), | ||
| checkpoints_considered_until, | ||
| message.data, | ||
| iteration, | ||
| ) | ||
| encoded_message = mpp_message.encoded() | ||
| self._server.deposit(recv_endpoint.ref(), encoded_message) | ||
|
|
@@ -245,10 +256,7 @@ def receive_message( | |
| RuntimeError: If the network connection had an error, or the | ||
| message number was incorrect. | ||
| """ | ||
| if port_name == "muscle_settings_in": | ||
| port = self._port_manager._muscle_settings_in | ||
| else: | ||
| port = self._port_manager.get_port(port_name) | ||
| port = self._port_manager.get_port(port_name) | ||
|
|
||
| if slot is None: | ||
| port_and_slot = port_name | ||
|
|
@@ -321,6 +329,8 @@ def receive_message( | |
|
|
||
| if isinstance(mpp_message.data, ClosePort): | ||
| port.set_closed(slot) | ||
| else: | ||
| self._timeline_manager.check_receive(port_name, slot) | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Isn't this check the first thing you should do when the user calls
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can call this after determining whether the incoming message is a ClosePort. We only know that after the client.receive() and decode step. This could potentially be moved earlier in the future if we switch from ClosePort messages to milestones. |
||
|
|
||
| message = Message( | ||
| mpp_message.timestamp, | ||
|
|
@@ -395,6 +405,11 @@ def receive_message( | |
| if isinstance(mpp_message.data, ClosePort): | ||
| _logger.debug(f"Port {port_and_slot} is now closed") | ||
|
|
||
| if not isinstance(mpp_message.data, ClosePort): | ||
| self._timeline_manager.check_received_message( | ||
| port_name, mpp_message.iteration, slot | ||
| ) | ||
|
|
||
| return message, mpp_message.saved_until | ||
|
|
||
| def shutdown(self) -> None: | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -13,7 +13,6 @@ | |
| from libmuscle.logging import LogLevel | ||
| from libmuscle.logging_handler import MuscleManagerHandler | ||
| from libmuscle.mmp_client import MMPClient | ||
| from libmuscle.mmsf_validator import MMSFValidator | ||
| from libmuscle.mpp_message import ClosePort | ||
| from libmuscle.port_manager import PortManager | ||
| from libmuscle.profiler import Profiler | ||
|
|
@@ -84,14 +83,6 @@ class InstanceFlags(Flag): | |
| :external:py:attr:`ymmsl.KeepsStateForNextUse.NECESSARY`). | ||
| """ | ||
|
|
||
| SKIP_MMSF_SEQUENCE_CHECKS = auto() | ||
| """Disable the checks whether the MMSF is strictly followed when sending/receiving | ||
| messages. | ||
|
|
||
| See :class:`~libmuscle.mmsf_validator.MMSFValidator` for a detailed description of | ||
| the checks. | ||
| """ | ||
|
|
||
|
Comment on lines
-87
to
-94
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To discuss: do we want to remove this InstanceFlag and force users to update their codes if they use this?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I removed this because if I understood you and Lourens correctly we would like to remove the possibility to skip the checks such that simulations can always work with well-defined timelines. However, now I removed this whole instance check but I can also re-add this and then give an error that you cannot skip the checks? Or would you like to give this possibility? |
||
|
|
||
| _CHECKPOINT_SUPPORT_MASK = ( | ||
| InstanceFlags.USES_CHECKPOINT_API | ||
|
|
@@ -205,12 +196,6 @@ def __init__( | |
| self._set_remote_log_level() | ||
| self._setup_profiling() | ||
| self._setup_receive_timeout() | ||
| # MMSFValidator needs a connected port manager, and does some logging | ||
| self._mmsf_validator = ( | ||
| None | ||
| if InstanceFlags.SKIP_MMSF_SEQUENCE_CHECKS in self._flags | ||
| else MMSFValidator(self._port_manager) | ||
| ) | ||
|
|
||
| def reuse_instance(self) -> bool: | ||
| """Decide whether to run this instance again. | ||
|
|
@@ -247,8 +232,6 @@ def reuse_instance(self) -> bool: | |
| :meth:`save_final_snapshot`, or the checkpointing tutorial. | ||
| """ | ||
| self._api_guard.verify_reuse_instance() | ||
| if self._mmsf_validator: | ||
| self._mmsf_validator.reuse_instance() | ||
|
|
||
| if self._do_reuse is not None: | ||
| # thank you, should_save_final_snapshot, for running this already | ||
|
|
@@ -257,8 +240,11 @@ def reuse_instance(self) -> bool: | |
| else: | ||
| do_reuse = self._decide_reuse_instance() | ||
|
|
||
| if self._do_resume and not self._do_init and self._mmsf_validator: | ||
| self._mmsf_validator.skip_f_init() | ||
| restored_from_intermediate = self._do_resume and not self._do_init | ||
| if restored_from_intermediate: | ||
| self._communicator._timeline_manager.restore_state( | ||
| self._snapshot_manager.resume_state() | ||
| ) | ||
|
|
||
| # now _first_run, _do_resume and _do_init are also set correctly | ||
|
|
||
|
|
@@ -278,6 +264,12 @@ def reuse_instance(self) -> bool: | |
| # store a None instead of a Message | ||
| self._save_snapshot(None, True, self.__f_init_max_timestamp) | ||
|
|
||
| if ( | ||
| not restored_from_intermediate | ||
| and self._communicator._timeline_manager.cycle_complete() | ||
| ): | ||
| self._communicator._timeline_manager.reset() | ||
|
|
||
|
IrisvdWerf marked this conversation as resolved.
Outdated
|
||
| if not do_reuse: | ||
| self.__shutdown() | ||
|
|
||
|
|
@@ -500,8 +492,6 @@ def send( | |
| slot: The slot to send the message on, if any. | ||
| """ | ||
| self.__check_port(port_name, slot, True) | ||
| if self._mmsf_validator: | ||
| self._mmsf_validator.check_send(port_name, slot) | ||
| if message.settings is None: | ||
| message = copy(message) | ||
| message.settings = self._settings_manager.overlay | ||
|
|
@@ -961,13 +951,15 @@ def _save_snapshot( | |
| """ | ||
| triggers = self._trigger_manager.get_triggers() | ||
| walltime = self._trigger_manager.elapsed_walltime() | ||
| timeline_state = self._communicator._timeline_manager.get_state() | ||
|
IrisvdWerf marked this conversation as resolved.
Outdated
|
||
| timestamp = self._snapshot_manager.save_snapshot( | ||
| message, | ||
| final, | ||
| triggers, | ||
| walltime, | ||
| f_init_max_timestamp, | ||
| self._settings_manager.overlay, | ||
| timeline_state, | ||
| ) | ||
| self._trigger_manager.update_checkpoints(timestamp) | ||
|
|
||
|
|
@@ -984,8 +976,6 @@ def __receive_message( | |
| description of those. | ||
| """ | ||
| self.__check_port(port_name, slot, False, True) | ||
| if self._mmsf_validator: | ||
| self._mmsf_validator.check_receive(port_name, slot) | ||
|
|
||
| port = self._port_manager.get_port(port_name) | ||
| if port.operator == Operator.F_INIT: | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.