Beispiel #1
0
    def make_node(self, *inputs):
        """
        Required: return an Apply instance representing the
        application of this Op to the provided inputs.

        All subclasses should over-ride this function.

        :Exceptions:
         - `MethodNotDefined`: the subclass does not override this method

        """
        raise utils.MethodNotDefined("make_node", type(self),
                                     self.__class__.__name__)
Beispiel #2
0
    def c_init_code_struct(self, node, name, sub):
        if 'init_code_struct' in self.code_sections:
            op_code = self.code_sections['init_code_struct']

            def_macros, undef_macros = self.get_c_macros(node, name)
            def_sub, undef_sub = self.get_sub_macros(sub)

            return os.linesep.join([def_macros, def_sub,
                                    op_code,
                                    undef_sub, undef_macros])
        else:
            raise utils.MethodNotDefined(
                'c_init_code_struct', type(self), type(self).__name__)
Beispiel #3
0
    def c_support_code(self):
        """Optional: Return utility code for use by a `Variable` or `Op` to be
        included at global scope prior to the rest of the code for this class.

        QUESTION: How many times will this support code be emitted for a graph
        with many instances of the same type?

        :Exceptions:
         - `MethodNotDefined`: Subclass does not implement this method

        """
        raise utils.MethodNotDefined("c_support_code", type(self),
                                     self.__class__.__name__)
Beispiel #4
0
    def c_compile_args(self):
        """Optional: Return a list of compile args recommended to compile the
        code returned by other methods in this class.

        Example: return ['-ffast-math']

        Compiler arguments related to headers, libraries and search paths should be provided
        via the functions `c_headers`, `c_libraries`, `c_header_dirs`, and `c_lib_dirs`.

        :Exceptions:
         - `MethodNotDefined`: Subclass does not implement this method

        """
        raise utils.MethodNotDefined("c_compile_args", type(self), self.__class__.__name__)
Beispiel #5
0
    def c_code_cleanup(self, node, name, inputs, outputs, sub):
        if 'code_cleanup' in self.code_sections:
            op_code = self.code_sections['code_cleanup']

            def_macros, undef_macros = self.get_c_macros(node, name)
            def_sub, undef_sub = self.get_sub_macros(sub)
            def_io, undef_io = self.get_io_macros(inp, out)

            return os.linesep.join([def_macros, def_sub, def_io,
                                    op_code,
                                    undef_io, undef_sub, undef_macros])
        else:
            raise utils.MethodNotDefined(
                'c_code_cleanup', type(self), type(self).__name__)
Beispiel #6
0
    def c_support_code_apply(self, node, name):

        if self.apply_code_marker in self.code_sections:
            apply_code = self.code_sections[self.apply_code_marker]

            if hasattr(self, 'check_inputs') and self.check_inputs == False:
                return apply_code
            else:
                define_macros, undef_macros = self.get_c_macros(node, name)
                return os.linesep.join(
                    [define_macros, apply_code, undef_macros])

        else:
            raise utils.MethodNotDefined("c_support_code_apply", type(self),
                                         self.__class__.__name__)
Beispiel #7
0
    def c_cleanup_code_struct(self, node, name):
        """
        Optional: return a code string specific to the apply to be
        inserted in the struct cleanup code.

        :param node: an Apply instance in the graph being compiled

        :param name: a unique name to distinguish you variables from
                     those of other nodes.

        :Exceptions:
        - `MethodNotDefined`: the subclass does not override this method
        """
        raise utils.MethodNotDefined("c_cleanup_code_struct", type(self),
                                     self.__class__.__name__)
Beispiel #8
0
    def c_support_code_struct(self, node, name):
        """Optional: Return utility code for use by an `Op` that will be
        inserted at struct scope, that can be specialized for the
        support of a particular `Apply` node.

        :param node: an Apply instance in the graph being compiled

        :param name: a unique name to distinguish you variables from
                     those of other nodes.

        :Exceptions:
         - `MethodNotDefined`: Subclass does not implement this method

        """
        raise utils.MethodNotDefined("c_support_code_struct", type(self),
                                     self.__class__.__name__)
Beispiel #9
0
    def c_support_code_apply(self, node, name):
        """Optional: Return utility code for use by an `Op` that will be inserted at global
        scope, that can be specialized for the support of a particular `Apply` node.

        :param node: an Apply instance in the graph being compiled

        :param node_id: a string or number that serves to uniquely identify this node.
        Symbol names defined by this support code should include the node_id, so that they can
        be called from the c_code, and so that they do not cause name collisions.

        :Exceptions:
         - `MethodNotDefined`: Subclass does not implement this method

        """
        raise utils.MethodNotDefined("c_support_code_apply", type(self),
                                     self.__class__.__name__)
Beispiel #10
0
    def c_cleanup_code_struct(self, node, struct_id):
        """
        Optional: return a code string specific to the apply to be
        inserted in the struct cleanup code.

        :param node: an Apply instance in the graph being compiled

        :param struct_id: a number that serves to uniquely identify
                          this code.  The c_code will receive another
                          sub parameter named struct_id that will
                          contain this name.

        :Exceptions:
        - `MethodNotDefined`: the subclass does not override this method
        """
        raise utils.MethodNotDefined("c_cleanup_code_struct", type(self),
                                     self.__class__.__name__)
Beispiel #11
0
    def c_lib_dirs(self):
        """Optional: Return a list of library search paths required by code returned by
        this class.

        For example: return ['/usr/local/lib', '/opt/weirdpath/build/libs'].

        Provide search paths for libraries, in addition to those in any relevant environment
        variables (e.g. LD_LIBRARY_PATH).

        Hint: for unix compilers, these are the things that get '-L' prefixed in the compiler
        cmdline.

        :Exceptions:
         - `MethodNotDefined`: Subclass does not implement this method

        """
        raise utils.MethodNotDefined("c_lib_dirs", type(self), self.__class__.__name__)
Beispiel #12
0
    def c_libraries(self):
        """Optional: Return a list of libraries required by code returned by
        this class.

        For example: return ['gsl', 'gslcblas', 'm', 'fftw3', 'g2c'].

        The compiler will search the directories specified by the environment
        variable LD_LIBRARY_PATH in addition to any returned by `c_lib_dirs`.

        Hint: for unix compilers, these are the things that get '-l' prefixed in the compiler
        cmdline.

        :Exceptions:
         - `MethodNotDefined`: Subclass does not implement this method

        """
        raise utils.MethodNotDefined("c_libraries", type(self), self.__class__.__name__)
Beispiel #13
0
    def c_header_dirs(self):
        """Optional: Return a list of header search paths required by code returned by
        this class.

        For example: return ['/usr/local/include', '/opt/weirdpath/src/include'].

        Provide search paths for headers, in addition to those in any relevant environment
        variables.

        Hint: for unix compilers, these are the things that get '-I' prefixed in the compiler
        cmdline.

        :Exceptions:
         - `MethodNotDefined`: Subclass does not implement this method

        """
        raise utils.MethodNotDefined("c_header_dirs", type(self), self.__class__.__name__)
Beispiel #14
0
    def c_headers(self):
        """Optional: Return a list of header files required by code returned by
        this class.

        For example: return ['<iostream>', '<math.h>', '/full/path/to/header.h']

        These strings will be prefixed with "#include " and inserted at the beginning of the c
        source code.

        Strings in this list that start neither with '<' nor '"' will be enclosed in
        double-quotes.

        :Exceptions:
         - `MethodNotDefined`: Subclass does not implement this method

        """
        raise utils.MethodNotDefined("c_headers", type(self), self.__class__.__name__)
Beispiel #15
0
    def c_no_compile_args(self):
        """Optional: Return a list of incompatible gcc compiler arguments.

        We will remove those arguments from the command line of gcc. So if
        another Op adds a compile arg in the graph that is incompatible
        with this Op, the incompatible arg will not be used.
        Useful for instance to remove -ffast-math.

        EXAMPLE

        WRITEME

        :Exceptions:
         - `MethodNotDefined`: the subclass does not override this method

        """
        raise utils.MethodNotDefined("c_no_compile_args", type(self), self.__class__.__name__)
Beispiel #16
0
    def c_support_code_struct(self, node, struct_id):
        """Optional: Return utility code for use by an `Op` that will be
        inserted at struct scope, that can be specialized for the
        support of a particular `Apply` node.

        :param node: an Apply instance in the graph being compiled

        :param struct_id: a number that serves to uniquely identify
                          this code.  The c_code will receive another
                          sub parameter named struct_id that will
                          contain this name.

        :Exceptions:
         - `MethodNotDefined`: Subclass does not implement this method

        """
        raise utils.MethodNotDefined("c_support_code_struct", type(self),
                                     self.__class__.__name__)
Beispiel #17
0
    def make_thunk(self):
        """
        This function must return a triplet (function, input_variables, output_variables)
        where function is a thunk that operates on the returned variables. If inplace
        is True, the input_variables and output_variables lists will be the same as the
        inputs and outputs of the graph provided to the L{Linker}. Else, independent
        variables will be returned.

        Example::
         x, y = Variable(Double), Variable(Double)
         e = x + y
         fgraph = FunctionGraph([x, y], [e])
         fn, (new_x, new_y), (new_e, ) = MyLinker(fgraph).make_thunk(inplace)
         new_x.data = 1.0
         new_y.data = 2.0
         fn()
         print new_e.data # 3.0
         print e.data # 3.0 iff inplace == True (else unknown)
        """
        raise utils.MethodNotDefined("make_thunk", type(self), self.__class__.__name__)
Beispiel #18
0
    def c_init_code_struct(self, node, name, sub):
        """
        Optional: return a code string specific to the apply
        to be inserted in the struct initialization code.

        :param node: an Apply instance in the graph being compiled

        :param name: a unique name to distinguish you variables from
                     those of other nodes.

        :param sub: a dictionary of values to substitute in the code.
                    Most notably it contains a 'fail' entry that you
                    should place in your code after setting a python
                    exception to indicate an error.

        :Exceptions:
         - `MethodNotDefined`: the subclass does not override this method
        """
        raise utils.MethodNotDefined("c_init_code_apply", type(self),
                                     self.__class__.__name__)
Beispiel #19
0
    def c_init_code_apply(self, node, name):
        """
        Optional: return a code string specific to the apply
        to be inserted in the module initialization code.

        :param node: an Apply instance in the graph being compiled

        :param name: a string or number that serves to uniquely
                     identify this node.  Symbol names defined by this
                     support code should include the name, so that
                     they can be called from the c_code, and so that
                     they do not cause name collisions.

        :note: This function is called in addition to c_init_code
               and will supplement whatever is returned from there.

        :Exceptions:
         - `MethodNotDefined`: the subclass does not override this method
        """
        raise utils.MethodNotDefined("c_init_code_apply", type(self),
                                     self.__class__.__name__)
Beispiel #20
0
    def c_code(self, node, name, inp, out, sub):
        if self.func_name is not None:
            assert 'code' not in self.code_sections
            func_name = self.func_name
            func_args = self.format_c_function_args(inp, out)
            fail = sub['fail']

            define_macros, undef_macros = self.get_c_macros(node,
                                                            name,
                                                            check_input=False)

            # Generate the C code
            return """
%(define_macros)s
{
  if (%(func_name)s(%(func_args)s) != 0) {
    %(fail)s
  }
}
%(undef_macros)s
""" % dict(func_name=self.func_name,
            fail=sub['fail'],
            func_args=self.format_c_function_args(inp, out),
            define_macros=define_macros,
            undef_macros=undef_macros)
        else:
            if 'code' in self.code_sections:
                op_code = self.code_sections['code']

                def_macros, undef_macros = self.get_c_macros(node, name)
                def_sub, undef_sub = self.get_sub_macros(sub)
                def_io, undef_io = self.get_io_macros(inp, out)

                return os.linesep.join([
                    def_macros, def_sub, def_io, op_code, undef_io, undef_sub,
                    undef_macros
                ])
            else:
                raise utils.MethodNotDefined('c_code', type(self),
                                             type(self).__name__)
Beispiel #21
0
    def c_init_code_struct(self, node, struct_id, sub):
        """
        Optional: return a code string specific to the apply
        to be inserted in the struct initialization code.

        :param node: an Apply instance in the graph being compiled

        :param struct_id: a number that serves to uniquely identify
                          this code.  The c_code will receive another
                          sub parameter named struct_id that will
                          contain this name.

        :param sub: a dictionary of values to substitute in the code.
                    Most notably it contains a 'fail' entry that you
                    should place in your code after setting a python
                    exception to indicate an error.

        :Exceptions:
         - `MethodNotDefined`: the subclass does not override this method
        """
        raise utils.MethodNotDefined("c_init_code_apply", type(self),
                                     self.__class__.__name__)
Beispiel #22
0
    def c_code(self, node, name, inputs, outputs, sub):
        """Required: Return the C implementation of an Op.

        Returns C code that does the computation associated to this `Op`,
        given names for the inputs and outputs.

        :Parameters:
         `node` : Apply instance
           The node for which we are compiling the current c_code.
           The same Op may be used in more than one node.
         `name` : A string
           A name that is automatically assigned and guaranteed to be
           unique.
         `inputs` : list of strings
           There is a string for each input of the function, and the
           string is the name of a C variable pointing to that input.
           The type of the variable depends on the declared type of
           the input.  There is a corresponding python variable that
           can be accessed by prepending "py_" to the name in the
           list.
         `outputs` : list of strings
           Each string is the name of a C variable where the Op should
           store its output.  The type depends on the declared type of
           the output.  There is a corresponding python variable that
           can be accessed by prepending "py_" to the name in the
           list.  In some cases the outputs will be preallocated and
           the value of the variable may be pre-filled.  The value for
           an unallocated output is type-dependent.
         `sub` : dict of strings
           extra symbols defined in `CLinker` sub symbols (such as 'fail').
           WRITEME

        :Exceptions:
         - `MethodNotDefined`: the subclass does not override this method

        """
        raise utils.MethodNotDefined('%s.c_code' \
                % self.__class__.__name__)
Beispiel #23
0
    def c_code_cleanup(self, node, name, inputs, outputs, sub):
        """Optional: Return C code to run after c_code, whether it failed or not.

        QUESTION: is this function optional?

        This is a convenient place to clean up things allocated by c_code().

        :Parameters:
         `node` : Apply instance
           WRITEME
         `name` : WRITEME
           WRITEME
         `inputs` : list of strings
           There is a string for each input of the function, and the string is the name of a C
           `PyObject` variable pointing to that input.
         `outputs` : list of strings
           Each string is the name of a `PyObject` pointer where the Op should store its
           variables.  This pointer could be NULL, or contain an object of the right
           Type (in the Theano sense) to store the output of the computation.
           For instance, for a TensorVariable, it will be a Numpy ndarray with
           the right number of dimensions, and the right dtype. However, its
           shape, or stride pattern, could not be adequate.
           It could be unchanged from the end of the previous execution, or allocated
           by another Op, or by the Mode.
         `sub` : dict of strings
           extra symbols defined in `CLinker` sub symbols (such as 'fail').
           WRITEME

        WRITEME

        :Exceptions:
         - `MethodNotDefined`: the subclass does not override this method

        """
        raise utils.MethodNotDefined('%s.c_code_cleanup' \
                % self.__class__.__name__)
Beispiel #24
0
    def c_code(self, node, name, inputs, outputs, sub):
        """Required: Return the C implementation of an Op.

        Returns C code that does the computation associated to this `Op`,
        given names for the inputs and outputs.

        :Parameters:
         `node` : Apply instance
           WRITEME
         `name` : WRITEME
           WRITEME
         `inputs` : list of strings
           There is a string for each input of the function, and the string is the name of a C
           `PyObject` variable pointing to that input.
         `outputs` : list of strings
           Each string is the name of a `PyObject` pointer where the Op should
           store its variables.  As of version 0.4.0, this pointer could be
           NULL, or contain an object allocated during a previous call to the
           same function, unchanged from the end of the previous execution.
           In a future version, there will be no guarantee on where that
           object will be created (it could be allocated during a previous
           execution, or by another Op, by the Mode, etc.). It will still
           be of an appropriate Type (in the Theano sense) to store the output
           of the computation: for instance, for a TensorVariable, it will be a
           Numpy ndarray with the right number of dimensions, and the right dtype.
           However, its shape, or stride pattern, could not be adequate.
         `sub` : dict of strings
           extra symbols defined in `CLinker` sub symbols (such as 'fail').
           WRITEME

        :Exceptions:
         - `MethodNotDefined`: the subclass does not override this method

        """
        raise utils.MethodNotDefined('%s.c_code' \
                % self.__class__.__name__)
Beispiel #25
0
 def f(self):
     if tag in self.code_sections:
         return self.code_sections[tag]
     else:
         raise utils.MethodNotDefined('c_' + tag, type(self),
                                      type(self).__name__)
Beispiel #26
0
 def c_init_code(self):
     if 'init_code' in self.code_sections:
         return [self.code_sections['init_code']]
     else:
         raise utils.MethodNotDefined(
             'c_init_code', type(self), type(self).__name__)