Esempio n. 1
0
    def update_output(self):
        """Override gmxapi.operation.ResourceManager.update_output because we handle paralellism as 0.0.7."""
        # For the moment, this is copy-pasted from gmxapi.operation.ResourceManager,
        # but the only part we need to override is the ensemble handling at `for i in range(self.ensemble_width)`
        # TODO: Reimplement as the resource factory and director for the operation target context.
        if not self.done():
            self.__operation_entrance_counter += 1
            if self.__operation_entrance_counter > 1:
                raise exceptions.ProtocolError('Bug detected: resource manager tried to execute operation twice.')
            if not self.done():
                # TODO: rewrite with the pattern that this block is directing and then resolving an operation in the
                #  operation's library/implementation context.

                ###
                # Note: this is the resource translation from gmxapi.operation context
                # to the dispatching runner director. It uses details of the gmxapi.operation.Context
                # and of the operation.

                # TODO: Dispatch/discover this resource factory from a canonical place.
                assert hasattr(self._runner_director, 'input_resource_factory')
                # Create on all ranks.
                input = self._runner_director.input_resource_factory(self)
                # End of action of the InputResourceDirector[Context, MdRunSubscription].
                ###

                # We are giving the director a resource that contains the subscription
                # to the dispatched work.

                publishing_resources = self.publishing_resources()
                for member in range(self.ensemble_width):
                    with publishing_resources(ensemble_member=member) as output:
                        resources = self._resource_factory(input=input, output=output)
                        runner = self._runner_director(resources)
                        runner.run()
Esempio n. 2
0
        def update_output(self):
            """Bring the output of the bound operation up to date.

            Execute the bound operation once if and only if it has not
            yet been run in the lifetime of this resource manager.

            Used internally to implement Futures for the local operation
            associated with this resource manager.

            TODO: We need a different implementation for an operation whose output
             is served by multiple resource managers. E.g. an operation whose output
             is available across the ensemble, but which should only be executed on
             a single ensemble member.
            """
            # This code is not intended to be reentrant. We make a modest attempt to
            # catch unexpected reentrance, but this is not (yet) intended to be a thread-safe
            # resource manager implementation.
            if not self.done:
                self.__operation_entrance_counter += 1
                if self.__operation_entrance_counter > 1:
                    raise exceptions.ProtocolError('Bug detected: resource manager tried to execute operation twice.')
                if not self.done:
                    with self.local_input() as input:
                        # Note: Resources are marked "done" by the resource manager
                        # when the following context manager completes.
                        # TODO: Allow both structured and singular output.
                        #  For simple functions, just capture and publish the return value.
                        with self.publishing_resources() as output:
                            self._runner(*input.args, output=output, **input.kwargs)