Exemplo n.º 1
0
        def wrapped_f(*args, **kwargs):
            # args   - <Tuple>      - Contains the objects that the function has been called with (positional).
            # kwargs - <Dictionary> - Contains the named objects that the function has been called with.

            is_replicated = self.kwargs['isReplicated']
            is_distributed = self.kwargs['isDistributed']
            # By default, each task is set to use one core.
            computingNodes = 1
            if 'computingNodes' in kwargs:
                # There is a @mpi decorator over task that overrides the
                # default value of computing nodes
                computingNodes = kwargs['computingNodes']
                del kwargs['computingNodes']

            # Check if this call is nested using the launch_pycompss_module
            # function from launch.py.
            is_nested = False
            istack = inspect.stack()
            for i_s in istack:
                if i_s[3] == 'launch_pycompss_module':
                    is_nested = True
                if i_s[3] == 'launch_pycompss_application':
                    is_nested = True

            if not i_am_at_master() and (not is_nested):
                # Task decorator worker body code.
                newTypes, newValues = self.worker_code(f, args, kwargs)
                return newTypes, newValues
            else:
                # Task decorator master body code.
                # Returns the future object that will be used instead of the
                # actual function return.
                fo = self.master_code(f, is_replicated, is_distributed,
                                      computingNodes, args, kwargs)
                return fo
Exemplo n.º 2
0
    def __call__(self, func):
        """
        Parse and set the mpi parameters within the task core element.
        :param func: Function to decorate
        :return: Decorated function.
        """
        if not self.scope:
            # from pycompss.api.dummy.mpi import mpi as dummy_mpi
            # d_m = dummy_mpi(self.args, self.kwargs)
            # return d_m.__call__(func)
            raise Exception(
                "The mpi decorator only works within PyCOMPSs framework.")

        if i_am_at_master():
            # master code
            from pycompss.runtime.binding import register_ce

            mod = inspect.getmodule(func)
            self.module = mod.__name__  # not func.__module__

            if (self.module == '__main__'
                    or self.module == 'pycompss.runtime.launch'):
                # The module where the function is defined was run as __main__,
                # we need to find out the real module name.

                # path=mod.__file__
                # dirs=mod.__file__.split(os.sep)
                # file_name=os.path.splitext(os.path.basename(mod.__file__))[0]

                # Get the real module name from our launch.py variable
                path = getattr(mod, "app_path")

                dirs = path.split(os.path.sep)
                file_name = os.path.splitext(os.path.basename(path))[0]
                mod_name = file_name

                i = len(dirs) - 1
                while i > 0:
                    new_l = len(path) - (len(dirs[i]) + 1)
                    path = path[0:new_l]
                    if "__init__.py" in os.listdir(path):
                        # directory is a package
                        i -= 1
                        mod_name = dirs[i] + '.' + mod_name
                    else:
                        break
                self.module = mod_name

            # Include the registering info related to @MPI

            # Retrieve the base coreElement established at @task decorator
            coreElement = func.__to_register__
            # Update the core element information with the mpi information
            coreElement.set_implType("MPI")
            binary = self.kwargs['binary']
            if 'workingDir' in self.kwargs:
                workingDir = self.kwargs['workingDir']
            else:
                workingDir = '[unassigned]'  # Empty or '[unassigned]'
            runner = self.kwargs['runner']
            implSignature = 'MPI.' + binary
            coreElement.set_implSignature(implSignature)
            implArgs = [binary, workingDir, runner]
            coreElement.set_implTypeArgs(implArgs)
            func.__to_register__ = coreElement
            # Do the task register if I am the top decorator
            if func.__who_registers__ == __name__:
                if __debug__:
                    logger.debug(
                        "[@MPI] I have to do the register of function %s in module %s"
                        % (func.__name__, self.module))
                register_ce(coreElement)
        else:
            # worker code
            pass

        @wraps(func)
        def mpi_f(*args, **kwargs):
            # This is executed only when called.
            if __debug__:
                logger.debug("Executing mpi_f wrapper.")

            # Set the computingNodes variable in kwargs for its usage
            # in @task decorator
            kwargs['computingNodes'] = self.kwargs['computingNodes']

            if len(args) > 0:
                # The 'self' for a method function is passed as args[0]
                slf = args[0]

                # Replace and store the attributes
                saved = {}
                for k, v in self.kwargs.items():
                    if hasattr(slf, k):
                        saved[k] = getattr(slf, k)
                        setattr(slf, k, v)

            # Call the method
            ret = func(*args, **kwargs)

            if len(args) > 0:
                # Put things back
                for k, v in saved.items():
                    setattr(slf, k, v)

            return ret

        mpi_f.__doc__ = func.__doc__
        return mpi_f
Exemplo n.º 3
0
    def __call__(self, func):

        if i_am_at_master():
            # master code

            mod = inspect.getmodule(func)
            self.module = mod.__name__    # not func.__module__

            if(self.module == '__main__' or
               self.module == 'pycompss.runtime.launch'):
                # The module where the function is defined was run as __main__,
                # we need to find out the real module name.

                # path=mod.__file__
                # dirs=mod.__file__.split(os.sep)
                # file_name=os.path.splitext(os.path.basename(mod.__file__))[0]

                # Get the real module name from our launch.py variable
                path = getattr(mod, "app_path")

                dirs = path.split(os.path.sep)
                file_name = os.path.splitext(os.path.basename(path))[0]
                mod_name = file_name

                i = len(dirs) - 1
                while i > 0:
                    new_l = len(path) - (len(dirs[i]) + 1)
                    path = path[0:new_l]
                    if "__init__.py" in os.listdir(path):
                        # directory is a package
                        i -= 1
                        mod_name = dirs[i] + '.' + mod_name
                    else:
                        break
                self.module = mod_name

            # Include the registering info related to @constraint

            # Retrieve the base coreElement established at @task decorator
            coreElement = func.__to_register__
            # Update the core element information with the constraints
            coreElement.set_implConstraints(self.kwargs)
            func.__to_register__ = coreElement
            # Do the task register if I am the top decorator
            if func.__who_registers__ == __name__:
                logger.debug("[@CONSTRAINT] I have to do the register of function %s in module %s" % (func.__name__, self.module))
                register_ce(coreElement)
        else:
            # worker code
            pass

        @wraps(func)
        def constrained_f(*args, **kwargs):
            # This is executed only when called.
            logger.debug("Executing constrained_f wrapper.")

            if len(args) > 0:
                # The 'self' for a method function is passed as args[0]
                slf = args[0]

                # Replace and store the attributes
                saved = {}
                for k, v in self.kwargs.items():
                    if hasattr(slf, k):
                        saved[k] = getattr(slf, k)
                        setattr(slf, k, v)

            # Call the method
            ret = func(*args, **kwargs)

            if len(args) > 0:
                # Put things back
                for k, v in saved.items():
                    setattr(slf, k, v)

            return ret
        constrained_f.__doc__ = func.__doc__
        return constrained_f
Exemplo n.º 4
0
    def __init__(self, *args, **kwargs):
        """
        If there are decorator arguments, the function to be decorated is
        not passed to the constructor!
        """
        logger.debug("Init @task decorator...")

        # Defaults
        self.args = args  # Not used
        self.kwargs = kwargs  # The only ones actually used: (decorators)
        self.is_instance = False

        # Pre-process decorator arguments
        from pycompss.api.parameter import Parameter
        from pycompss.api.parameter import IN
        from pycompss.api.parameter import TYPE
        from pycompss.api.parameter import DIRECTION

        # Reserved PyCOMPSs keywords and default values

        reserved_keywords = {
            'isModifier': True,
            'returns': False,
            'priority': False,
            'isReplicated': False,
            'isDistributed': False,
            'varargsType': IN
        }

        for (reserved_keyword, default_value) in reserved_keywords.items():
            if reserved_keyword not in self.kwargs:
                self.kwargs[reserved_keyword] = default_value

        # Remove old args
        for old_vararg in [
                x for x in self.kwargs.keys() if x.startswith('*args')
        ]:
            self.kwargs.pop(old_vararg)

        import copy

        if i_am_at_master():
            for arg_name in self.kwargs.keys():
                if arg_name not in [
                        'isModifier', 'returns', 'priority', 'isReplicated',
                        'isDistributed'
                ]:
                    # Prevent p.value from being overwritten later by ensuring
                    # each Parameter is a separate object
                    p = self.kwargs[arg_name]
                    pcopy = copy.copy(p)  # shallow copy
                    self.kwargs[arg_name] = pcopy

        if self.kwargs['isModifier']:
            direction = DIRECTION.INOUT
        else:
            direction = DIRECTION.IN

        # Add callee object parameter
        self.kwargs['self'] = Parameter(p_type=TYPE.OBJECT,
                                        p_direction=direction)

        # Check the return type:
        if self.kwargs['returns']:
            # This condition is interesting, because a user can write
            # returns=list
            # However, lists have the attribute __len__ but raise an exception.
            # Since the user does not indicate the length, it will be managed
            # as a single return.
            # When the user specifies the length, it is possible to manage the
            # elements independently.
            if not hasattr(self.kwargs['returns'],
                           '__len__') or type(self.kwargs['returns']) is type:
                # Simple return
                retType = getCOMPSsType(self.kwargs['returns'])
                self.kwargs['compss_retvalue'] = Parameter(
                    p_type=retType, p_direction=DIRECTION.OUT)
            else:
                # Multi return
                i = 0
                returns = []
                for r in self.kwargs['returns']:  # This adds only one? - yep
                    retType = getCOMPSsType(r)
                    returns.append(
                        Parameter(p_type=retType, p_direction=DIRECTION.OUT))
                self.kwargs['compss_retvalue'] = tuple(returns)

        logger.debug("Init @task decorator finished.")
Exemplo n.º 5
0
    def __call__(self, f):
        """
        If there are decorator arguments, __call__() is only called
        once, as part of the decoration process! You can only give
        it a single argument, which is the function object.
        """
        # Assume it is an instance method if the first parameter of the
        # function is called 'self'
        # "I would rely on the convention that functions that will become
        # methods have a first argument named self, and other functions don't.
        # Fragile, but then, there's no really solid way."
        self.spec_args = inspect.getargspec(f)

        # Set default booleans
        self.is_instance = False
        self.is_classmethod = False  # not used currently in this scope, only when registering the task
        self.has_varargs = False
        self.has_keywords = False
        self.has_defaults = False
        self.has_return = False

        # Question: Will the first condition evaluate to false? spec_args will
        # always be a named tuple, so it will always return true if evaluated
        # as a bool
        # Answer: The first condition evaluates if args exists (a list) and is
        # not empty in the spec_args. The second checks if the first argument
        # in that list is 'self'. In case that the args list exists and its
        # first element is self, then the function is considered as an instance
        # function (task defined within a class).
        if self.spec_args.args and self.spec_args.args[0] == 'self':
            self.is_instance = True

        # Check if contains *args
        if self.spec_args.varargs is not None:
            self.has_varargs = True

        # Check if contains **kwargs
        if self.spec_args.keywords is not None:
            self.has_keywords = True

        # Check if has default values
        if self.spec_args.defaults is not None:
            self.has_defaults = True

        # Check if the keyword returns has been specified by the user.
        if self.kwargs['returns']:
            self.has_return = True
            self.spec_args.args.append('compss_retvalue')

        # Get module (for invocation purposes in the worker)
        mod = inspect.getmodule(f)
        self.module = mod.__name__

        if (self.module == '__main__'
                or self.module == 'pycompss.runtime.launch'):
            # the module where the function is defined was run as __main__,
            # we need to find out the real module name

            # Get the real module name from our launch.py app_path global variable
            try:
                path = getattr(mod, "app_path")
            except AttributeError:
                # This exception is raised when the runtime is not running and
                # the @task decorator is used.
                print(
                    "ERROR!!! The runtime has not been started yet. The function will be ignored."
                )
                print(
                    "Please, start the runtime before using task decorated functions in order to avoid this error."
                )
                print(
                    "Suggestion: Use the 'runcompss' command or the 'start' function from pycompss.interactive module depending on your needs."
                )
                return

            # Get the file name
            file_name = os.path.splitext(os.path.basename(path))[0]

            # Do any necessary preprocessing action before executing any code
            if file_name.startswith('InteractiveMode'):
                # If the file_name starts with 'InteractiveMode' means that
                # the user is using PyCOMPSs from jupyter-notebook.
                # Convention between this file and interactive.py
                # In this case it is necessary to do a pre-processing step
                # that consists of putting all user code that may be executed
                # in the worker on a file.
                # This file has to be visible for all workers.
                updateTasksCodeFile(f, path)
            else:
                # work as always
                pass

            # Get the module
            self.module = getModuleName(path, file_name)

        # The registration needs to be done only in the master node
        if i_am_at_master():
            registerTask(f, self.module, self.is_instance)

        # Modified variables until now that will be used later:
        #   - self.spec_args    : Function argspect (Named tuple)
        #                         e.g. ArgSpec(args=['a', 'b', 'compss_retvalue'], varargs=None, keywords=None, defaults=None)
        #   - self.is_instance  : Boolean - if the function is an instance (contains self in the spec_args)
        #   - self.has_varargs  : Boolean - if the function has *args
        #   - self.has_keywords : Boolean - if the function has **kwargs
        #   - self.has_defaults : Boolean - if the function has default values
        #   - self.has_return   : Boolean - if the function has return
        #   - self.module       : module as string (e.g. test.kmeans)
        #   - is_replicated     : Boolean - if the task is replicated
        #   - is_distributed    : Boolean - if the task is distributed
        # Other variables that will be used:
        #   - f                 : Decorated function
        #   - self.args         : Decorator args tuple (usually empty)
        #   - self.kwargs       : Decorator keywords dictionary.
        #                         e.g. {'priority': True, 'isModifier': True, 'returns': <type 'dict'>,
        #                               'self': <pycompss.api.parameter.Parameter instance at 0xXXXXXXXXX>,
        #                               'compss_retvalue': <pycompss.api.parameter.Parameter instance at 0xXXXXXXXX>}

        @wraps(f)
        def wrapped_f(*args, **kwargs):
            # args   - <Tuple>      - Contains the objects that the function has been called with (positional).
            # kwargs - <Dictionary> - Contains the named objects that the function has been called with.

            is_replicated = self.kwargs['isReplicated']
            is_distributed = self.kwargs['isDistributed']
            computingNodes = 1
            if 'computingNodes' in kwargs:
                # There is a @mpi decorator over task that overrides the
                # default value of computing nodes
                computingNodes = kwargs['computingNodes']
                del kwargs['computingNodes']

            # Check if this call is nested using the launch_pycompss_module
            # function from launch.py.
            is_nested = False
            istack = inspect.stack()
            for i_s in istack:
                if i_s[3] == 'launch_pycompss_module':
                    is_nested = True
                if i_s[3] == 'launch_pycompss_application':
                    is_nested = True

            if not i_am_at_master() and (not is_nested):
                # Task decorator worker body code.
                newTypes, newValues = workerCode(f, self.is_instance,
                                                 self.has_varargs,
                                                 self.has_keywords,
                                                 self.has_defaults,
                                                 self.has_return, args, kwargs,
                                                 self.kwargs, self.spec_args)
                return newTypes, newValues
            else:
                # Task decorator master body code.
                # Returns the future object that will be used instead of the
                # actual function return.
                fo = masterCode(f, self.module, self.is_instance,
                                self.has_varargs, self.has_keywords,
                                self.has_defaults, self.has_return,
                                is_replicated, is_distributed, computingNodes,
                                args, self.args, kwargs, self.kwargs,
                                self.spec_args)
                return fo

        return wrapped_f
Exemplo n.º 6
0
    def __init__(self, *args, **kwargs):
        """
        If there are decorator arguments, the function to be decorated is
        not passed to the constructor!
        """
        from pycompss.util.location import i_am_within_scope

        # Check if under the PyCOMPSs scope
        if i_am_within_scope():
            from pycompss.util.location import i_am_at_master
            from pycompss.api.parameter import IN

            self.scope = True

            if __debug__:
                logger.debug("Init @task decorator...")

            # Defaults
            self.args = args  # Not used
            self.kwargs = kwargs  # The only ones actually used: (decorators)

            # Pre-process decorator arguments

            # Reserved PyCOMPSs keywords and default values
            reserved_keywords = {
                'isModifier': True,
                'returns': False,
                'priority': False,
                'isReplicated': False,
                'isDistributed': False,
                'varargsType': IN
            }

            # Set reserved keyword default values in self.kwargs
            for (reserved_keyword, default_value) in reserved_keywords.items():
                if reserved_keyword not in self.kwargs:
                    self.kwargs[reserved_keyword] = default_value

            # Remove old args
            for old_vararg in [
                    x for x in self.kwargs.keys() if x.startswith('*args')
            ]:
                self.kwargs.pop(old_vararg)

            if i_am_at_master():
                for arg_name in self.kwargs.keys():
                    if arg_name not in reserved_keywords.keys():
                        # Prevent p.value from being overwritten later by ensuring
                        # each Parameter is a separate object
                        p = self.kwargs[arg_name]
                        pcopy = copy.copy(p)  # shallow copy
                        self.kwargs[arg_name] = pcopy

            if __debug__:
                logger.debug("Init @task decorator finished.")
        else:
            # Not under the PyCOMPSs scope
            self.scope = False
            # Defaults
            self.args = args
            self.kwargs = kwargs
Exemplo n.º 7
0
    def __call__(self, f):
        """
        If there are decorator arguments, __call__() is only called
        once, as part of the decoration process! You can only give
        it a single argument, which is the function object.
        """
        # Check if under the PyCOMPSs scope
        if not self.scope:
            return self.__not_under_pycompss_scope(f)

        # Imports
        from pycompss.api.parameter import Parameter
        from pycompss.api.parameter import TYPE
        from pycompss.api.parameter import DIRECTION
        from pycompss.util.interactive_helpers import updateTasksCodeFile
        from pycompss.util.location import i_am_at_master

        if __debug__:
            logger.debug("Call in @task decorator...")

        # Assume it is an instance method if the first parameter of the
        # function is called 'self'
        # "I would rely on the convention that functions that will become
        # methods have a first argument named self, and other functions don't.
        # Fragile, but then, there's no really solid way."
        self.f_argspec = inspect.getargspec(f)

        # Set default booleans
        self.is_instance = False
        self.is_classmethod = False
        self.has_varargs = False
        self.has_keywords = False
        self.has_defaults = False
        self.has_return = False
        self.has_multireturn = False

        # Step 1.- Check if it is an instance method.
        # Question: Will the first condition evaluate to false? spec_args will
        # always be a named tuple, so it will always return true if evaluated
        # as a bool
        # Answer: The first condition evaluates if args exists (a list) and is
        # not empty in the spec_args. The second checks if the first argument
        # in that list is 'self'. In case that the args list exists and its
        # first element is self, then the function is considered as an instance
        # function (task defined within a class).
        if self.f_argspec.args and self.f_argspec.args[0] == 'self':
            self.is_instance = True
            if self.kwargs['isModifier']:
                direction = DIRECTION.INOUT
            else:
                direction = DIRECTION.IN
            # Add callee object parameter
            self.kwargs['self'] = Parameter(p_type=TYPE.OBJECT,
                                            p_direction=direction)

        # Step 2.- Check if it is a class method.
        # The check of 'cls' may be weak but it is PEP8 style agreements.
        if self.f_argspec.args and self.f_argspec.args[0] == 'cls':
            self.is_classmethod = True
            # Add class object parameter
            self.kwargs['self'] = Parameter(p_type=TYPE.OBJECT,
                                            p_direction=DIRECTION.IN)

        # Step 3.- Check if it has varargs (contains *args?)
        # Check if contains *args
        if self.f_argspec.varargs is not None:
            self.has_varargs = True

        # Step 4.- Check if it has keyword arguments (contains **kwargs?)
        # Check if contains **kwargs
        if self.f_argspec.keywords is not None:
            self.has_keywords = True

        # Step 5.- Check if it has default values
        # Check if has default values
        if self.f_argspec.defaults is not None:
            self.has_defaults = True

        # Step 6.- Check if the keyword returns has been specified by the user.
        # Check if the keyword returns has been specified by the user.
        if self.kwargs['returns']:
            self.has_return = True
            self.f_argspec.args.append(
                'compss_retvalue'
            )  # TODO: WHY THIS VARIABLE? THE INFORMATION IS IN SELF.KWARGS['COMPSS_RETVALUE']
            self.__update_return_type()
        else:
            # If no returns statement found, double check to see if the user has specified a return statement.
            self.__update_return_if_no_returns(f)

        # Get module (for invocation purposes in the worker)
        mod = inspect.getmodule(f)
        self.module = mod.__name__

        if self.module == '__main__' or self.module == 'pycompss.runtime.launch':
            # the module where the function is defined was run as __main__,
            # we need to find out the real module name

            # Get the real module name from our launch.py app_path global variable
            try:
                path = getattr(mod, "app_path")
            except AttributeError:
                # This exception is raised when the runtime is not running and the @task decorator is used.
                # The runtime has not been started yet.
                return self.__not_under_pycompss_scope(f)

            # Get the file name
            file_name = os.path.splitext(os.path.basename(path))[0]

            # Do any necessary preprocessing action before executing any code
            if file_name.startswith('InteractiveMode'):
                # If the file_name starts with 'InteractiveMode' means that
                # the user is using PyCOMPSs from jupyter-notebook.
                # Convention between this file and interactive.py
                # In this case it is necessary to do a pre-processing step
                # that consists of putting all user code that may be executed
                # in the worker on a file.
                # This file has to be visible for all workers.
                updateTasksCodeFile(f, path)
            else:
                # work as always
                pass

            # Get the module
            self.module = get_module_name(path, file_name)

        # The registration needs to be done only in the master node
        if i_am_at_master():
            self.__register_task(f)

        # Modified variables until now that will be used later:
        #   - self.f_argspec        : Function argspect (Named tuple)
        #                             e.g. ArgSpec(args=['a', 'b', 'compss_retvalue'], varargs=None, keywords=None, defaults=None)
        #   - self.is_instance      : Boolean - if the function is an instance (contains self in the f_argspec)
        #   - self.is_classmethod   : Boolean - if the function is a classmethod (contains cls in the f_argspec)
        #   - self.has_varargs      : Boolean - if the function has *args
        #   - self.has_keywords     : Boolean - if the function has **kwargs
        #   - self.has_defaults     : Boolean - if the function has default values
        #   - self.has_return       : Boolean - if the function has return
        #   - self.has_multireturn  : Boolean - if the function has multireturn
        #   - self.module_name      : String  - Module name (e.g. test.kmeans)
        #   - is_replicated         : Boolean - if the task is replicated
        #   - is_distributed    : Boolean - if the task is distributed
        # Other variables that will be used:
        #   - f                 : Decorated function
        #   - self.args         : Decorator args tuple (usually empty)
        #   - self.kwargs       : Decorator keywords dictionary.
        #                         e.g. {'priority': True, 'isModifier': True, 'returns': <type 'dict'>,
        #                               'self': <pycompss.api.parameter.Parameter instance at 0xXXXXXXXXX>,
        #                               'compss_retvalue': <pycompss.api.parameter.Parameter instance at 0xXXXXXXXX>}

        if __debug__:
            logger.debug("Call in @task decorator finished.")

        @wraps(f)
        def wrapped_f(*args, **kwargs):
            # args   - <Tuple>      - Contains the objects that the function has been called with (positional).
            # kwargs - <Dictionary> - Contains the named objects that the function has been called with.

            is_replicated = self.kwargs['isReplicated']
            is_distributed = self.kwargs['isDistributed']
            # By default, each task is set to use one core.
            computingNodes = 1
            if 'computingNodes' in kwargs:
                # There is a @mpi decorator over task that overrides the
                # default value of computing nodes
                computingNodes = kwargs['computingNodes']
                del kwargs['computingNodes']

            # Check if this call is nested using the launch_pycompss_module
            # function from launch.py.
            is_nested = False
            istack = inspect.stack()
            for i_s in istack:
                if i_s[3] == 'launch_pycompss_module':
                    is_nested = True
                if i_s[3] == 'launch_pycompss_application':
                    is_nested = True

            if not i_am_at_master() and (not is_nested):
                # Task decorator worker body code.
                newTypes, newValues = self.worker_code(f, args, kwargs)
                return newTypes, newValues
            else:
                # Task decorator master body code.
                # Returns the future object that will be used instead of the
                # actual function return.
                fo = self.master_code(f, is_replicated, is_distributed,
                                      computingNodes, args, kwargs)
                return fo

        return wrapped_f
Exemplo n.º 8
0
    def __call__(self, func):
        """
        Parse and set the implementation parameters within the task core element.
        :param func: Function to decorate
        :return: Decorated function.
        """
        if not self.scope:
            # from pycompss.api.dummy.implement import implement as dummy_implement
            # d_i = dummy_implement(self.args, self.kwargs)
            # return d_i.__call__(func)
            raise Exception("The implement decorator only works within PyCOMPSs framework.")

        if i_am_at_master():
            # master code
            from pycompss.runtime.binding import register_ce

            mod = inspect.getmodule(func)
            self.module = mod.__name__    # not func.__module__

            if(self.module == '__main__' or
               self.module == 'pycompss.runtime.launch'):
                # The module where the function is defined was run as __main__,
                # we need to find out the real module name.

                # path=mod.__file__
                # dirs=mod.__file__.split(os.sep)
                # file_name=os.path.splitext(os.path.basename(mod.__file__))[0]

                # Get the real module name from our launch.py variable
                path = getattr(mod, "app_path")

                dirs = path.split(os.path.sep)
                file_name = os.path.splitext(os.path.basename(path))[0]
                mod_name = file_name

                i = len(dirs) - 1
                while i > 0:
                    new_l = len(path) - (len(dirs[i]) + 1)
                    path = path[0:new_l]
                    if "__init__.py" in os.listdir(path):
                        # directory is a package
                        i -= 1
                        mod_name = dirs[i] + '.' + mod_name
                    else:
                        break
                self.module = mod_name

            # Include the registering info related to @MPI

            # Retrieve the base coreElement established at @task decorator
            coreElement = func.__to_register__
            # Update the core element information with the mpi information
            ce_signature = coreElement.get_ce_signature()
            implSignature = ce_signature
            coreElement.set_implSignature(implSignature)

            anotherClass = self.kwargs['source_class']
            anotherMethod = self.kwargs['method']
            ce_signature = anotherClass + '.' + anotherMethod
            coreElement.set_ce_signature(ce_signature)

            # This is not needed since the arguments are already set by the
            # task decorator.
            # implArgs = [anotherClass, anotherMethod]
            # coreElement.set_implTypeArgs(implArgs)

            coreElement.set_implType("METHOD")
            func.__to_register__ = coreElement
            # Do the task register if I am the top decorator
            if func.__who_registers__ == __name__:
                if __debug__:
                    logger.debug("[@IMPLEMENT] I have to do the register of function %s in module %s" % (func.__name__, self.module))
                register_ce(coreElement)
        else:
            # worker code
            pass

        @wraps(func)
        def implement_f(*args, **kwargs):
            # This is executed only when called.
            if __debug__:
                logger.debug("Executing implement_f wrapper.")

            # The 'self' for a method function is passed as args[0]
            slf = args[0]

            # Replace and store the attributes
            saved = {}
            for k, v in self.kwargs.items():
                if hasattr(slf, k):
                    saved[k] = getattr(slf, k)
                    setattr(slf, k, v)

            # Call the method
            ret = func(*args, **kwargs)

            # Put things back
            for k, v in saved.items():
                setattr(slf, k, v)

            return ret
        implement_f.__doc__ = func.__doc__
        return implement_f
Exemplo n.º 9
0
    def __call__(self, func):

        if i_am_at_master():
            # master code
            mod = inspect.getmodule(func)
            self.module = mod.__name__  # not func.__module__

            if (self.module == '__main__'
                    or self.module == 'pycompss.runtime.launch'):
                # The module where the function is defined was run as __main__,
                # we need to find out the real module name.

                # path=mod.__file__
                # dirs=mod.__file__.split(os.sep)
                # file_name=os.path.splitext(os.path.basename(mod.__file__))[0]

                # Get the real module name from our launch.py variable
                path = getattr(mod, "app_path")

                dirs = path.split(os.path.sep)
                file_name = os.path.splitext(os.path.basename(path))[0]
                mod_name = file_name

                i = len(dirs) - 1
                while i > 0:
                    new_l = len(path) - (len(dirs[i]) + 1)
                    path = path[0:new_l]
                    if "__init__.py" in os.listdir(path):
                        # directory is a package
                        i -= 1
                        mod_name = dirs[i] + '.' + mod_name
                    else:
                        break
                self.module = mod_name

            # Include the registering info related to @MPI

            # Retrieve the base coreElement established at @task decorator
            coreElement = func.__to_register__
            # Update the core element information with the mpi information
            coreElement.set_implType("DECAF")
            if 'workingDir' in self.kwargs:
                workingDir = self.kwargs['workingDir']
            else:
                workingDir = '[unassigned]'  # Empty or '[unassigned]'
            if 'mpiRunner' in self.kwargs:
                runner = self.kwargs['mpiRunner']
            else:
                runner = 'mpirun'
            dfScript = self.kwargs['dfScript']
            if 'dfExecutor' in self.kwargs:
                dfExecutor = self.kwargs['dfExecutor']
            else:
                dfExecutor = '[unassigned]'  # Empty or '[unassigned]'
            if 'dfLib' in self.kwargs:
                dfLib = self.kwargs['dfLib']
            else:
                dfLib = '[unassigned]'  # Empty or '[unassigned]'
            implSignature = 'DECAF.' + dfScript
            coreElement.set_implSignature(implSignature)
            implArgs = [dfScript, dfExecutor, dfLib, workingDir, runner]
            coreElement.set_implTypeArgs(implArgs)
            func.__to_register__ = coreElement
            # Do the task register if I am the top decorator
            if func.__who_registers__ == __name__:
                logger.debug(
                    "[@DECAF] I have to do the register of function %s in module %s"
                    % (func.__name__, self.module))
                register_ce(coreElement)
        else:
            # worker code
            pass

        @wraps(func)
        def decaf_f(*args, **kwargs):
            # This is executed only when called.
            logger.debug("Executing decaf_f wrapper.")

            # Set the computingNodes variable in kwargs for its usage in @task decorator
            kwargs['computingNodes'] = self.kwargs['computingNodes']

            if len(args) > 0:
                # The 'self' for a method function is passed as args[0]
                slf = args[0]

                # Replace and store the attributes
                saved = {}
                for k, v in self.kwargs.items():
                    if hasattr(slf, k):
                        saved[k] = getattr(slf, k)
                        setattr(slf, k, v)

            # Call the method
            ret = func(*args, **kwargs)

            if len(args) > 0:
                # Put things back
                for k, v in saved.items():
                    setattr(slf, k, v)

            return ret

        decaf_f.__doc__ = func.__doc__
        return decaf_f