提交 b1247c12 authored 作者: Pierre Luc Carrier's avatar Pierre Luc Carrier

Replaced <<<<APPLY_NAME_PLACEHOLDER>>>> with macro APPLY_SPECIFIC

上级 2a509e11
...@@ -715,7 +715,7 @@ The new op is defined inside a Python file with the following code : ...@@ -715,7 +715,7 @@ The new op is defined inside a Python file with the following code :
__props__ = () __props__ = ()
func_file = "./vectorTimesVector.c" func_file = "./vectorTimesVector.c"
func_name = "vector_times_vector_<<<<NODE_NAME_PLACEHOLDER>>>>" func_name = "APPLY_SPECIFIC(vector_times_vector)"
def __init__(self): def __init__(self):
super(VectorTimesVector, self).__init__(self.func_file, super(VectorTimesVector, self).__init__(self.func_file,
...@@ -735,7 +735,6 @@ The new op is defined inside a Python file with the following code : ...@@ -735,7 +735,6 @@ The new op is defined inside a Python file with the following code :
return gof.Apply(self, [x, y], [output_var]) return gof.Apply(self, [x, y], [output_var])
And the following is the C implementation of the op, defined in an external And the following is the C implementation of the op, defined in an external
C file named vectorTimesVector.c : C file named vectorTimesVector.c :
...@@ -751,7 +750,7 @@ C file named vectorTimesVector.c : ...@@ -751,7 +750,7 @@ C file named vectorTimesVector.c :
#endif #endif
// Apply-specific support code // Apply-specific support code
void vector_elemwise_mult_<<<<NODE_NAME_PLACEHOLDER>>>>( void APPLY_SPECIFIC(vector_elemwise_mult)(
DTYPE_INPUT_0* x_ptr, int x_str, DTYPE_INPUT_0* x_ptr, int x_str,
DTYPE_INPUT_1* y_ptr, int y_str, DTYPE_INPUT_1* y_ptr, int y_str,
DTYPE_OUTPUT_0* z_ptr, int z_str, int nbElements) DTYPE_OUTPUT_0* z_ptr, int z_str, int nbElements)
...@@ -762,9 +761,9 @@ C file named vectorTimesVector.c : ...@@ -762,9 +761,9 @@ C file named vectorTimesVector.c :
} }
// Main function // Main function
int vector_times_vector_<<<<NODE_NAME_PLACEHOLDER>>>>(PyArrayObject* input0, int APPLY_SPECIFIC(vector_times_vector)(PyArrayObject* input0,
PyArrayObject* input1, PyArrayObject* input1,
PyArrayObject** output0) PyArrayObject** output0)
{ {
// Validate that the inputs have the same shape // Validate that the inputs have the same shape
if ( !vector_same_shape(input0, input1)) if ( !vector_same_shape(input0, input1))
...@@ -798,7 +797,7 @@ C file named vectorTimesVector.c : ...@@ -798,7 +797,7 @@ C file named vectorTimesVector.c :
} }
// Perform the actual vector-vector multiplication // Perform the actual vector-vector multiplication
vector_elemwise_mult_<<<<NODE_NAME_PLACEHOLDER>>>>( APPLY_SPECIFIC(vector_elemwise_mult)(
(DTYPE_INPUT_0*)PyArray_DATA(input0), (DTYPE_INPUT_0*)PyArray_DATA(input0),
PyArray_STRIDES(input0)[0] / ITEMSIZE_INPUT_0, PyArray_STRIDES(input0)[0] / ITEMSIZE_INPUT_0,
(DTYPE_INPUT_1*)PyArray_DATA(input1), (DTYPE_INPUT_1*)PyArray_DATA(input1),
...@@ -892,9 +891,9 @@ defined: ...@@ -892,9 +891,9 @@ defined:
In the same way, the macros ``DTYPE_OUTPUT_{i}``, ``ITEMSIZE_OUTPUT_{i}`` and In the same way, the macros ``DTYPE_OUTPUT_{i}``, ``ITEMSIZE_OUTPUT_{i}`` and
``TYPENUM_OUTPUT_{i}`` are defined for every output 'i' of the op. ``TYPENUM_OUTPUT_{i}`` are defined for every output 'i' of the op.
The ``COp`` class also defines the macro ``<<<<NODE_NAME_PLACEHOLDER>>>>`` The ``COp`` class also defines the macro ``APPLY_SPECIFIC(str)`` which will
which will automatically be replaced by the name of the Apply node that applies automatically append the name of the :ref:`Apply node that applies the Op at
the op. the end of the provided ``str``. The use of this macro is discussed below.
You should be aware, however, that these macros are apply-specific. As such, You should be aware, however, that these macros are apply-specific. As such,
any function that uses them is considered to contain apply-specific code. any function that uses them is considered to contain apply-specific code.
...@@ -917,25 +916,33 @@ between the different versions of the apply-specific code. The code that ...@@ -917,25 +916,33 @@ between the different versions of the apply-specific code. The code that
wasn't apply-specific was simply defined in the ``c_support_code()`` method. wasn't apply-specific was simply defined in the ``c_support_code()`` method.
When using the ``COp`` class, we still have to make the distinction between When using the ``COp`` class, we still have to make the distinction between
apply- specific and apply-agnostic support code but we express it differently apply-specific and apply-agnostic support code but we express it differently
in the code since it is all defined in the same external C file. in the code since it is all defined in the same external C file.
Apply-agnostic code should now be defined inside a ``ifndef``-``define`` Apply-agnostic code should now be defined inside a ``ifndef``-``define``
structure (like the function ``vector_same_shape()`` in the example above) to structure (like the function ``vector_same_shape()`` in the example above) to
ensure that it is only defined once. On the other hand, apply-specific ensure that it is only defined once. On the other hand, apply-specific
functions and global variables should simply include the macro functions and global variables only need to include the name of the
``<<<<NODE_NAME_PLACEHOLDER>>>>`` in their names. When the Theano function is :ref:`Apply` node in their names. To achieve this, the macro
compiled, this macro will be automatically replaced by the name of the ``APPLY_SPECIFIC(str)`` should be used when defining those elements as well as
:ref:`Apply` node that applies this op, thus making those functions and when referring to them. In the above example, this macro is used when defining
variables apply-specific. The function the functions ``vector_elemwise_mult()`` and ``vector_times_vector()`` as well
``vector_elemwise_mult_<<<<NODE_NAME_PLACEHOLDER>>>>()`` is an example of how to as when calling function ``vector_elemwise_mult()`` from inside
do this. ``vector_times_vector()``.
:note: :note:
The macro ``<<<<NODE_NAME_PLACEHOLDER>>>>`` should only ever be used for The macro ``APPLY_SPECIFIC(str)`` should only ever be used for
apply-specific code. It should not be used for apply-agnostic code. apply-specific code. It should not be used for apply-agnostic code.
The rules for knowing if a piece of code should be treated as apply-specific The rules for knowing if a piece of code should be treated as apply-specific
or not are simple; if it uses any of the macros defined by the class ``COp`` or not are simple; if it uses any of the macros defined by the class ``COp``
then it is apply-specific, if it calls any apply-specific code then it is then it is apply-specific, if it calls any apply-specific code then it is
apply-specific. Otherwise, it is apply-agnostic. apply-specific. Otherwise, it is apply-agnostic.
In the above example, the ``function vector_same_shape()`` is apply-agnostic
because it uses none of the macros defined by the class ``COp`` and it doesn't
rely on any apply-specific code. The function ``vector_elemwise_mult()`` is
apply-specific because it uses the macros defined by ``COp``. Finally, the
function ``vector_times_vector()`` is apply-specific because it uses those
same macros and also because it calls ``vector_elemwise_mult()`` which is an
apply-specific function.
...@@ -1001,14 +1001,12 @@ class COp(Op): ...@@ -1001,14 +1001,12 @@ class COp(Op):
return hash(self.func_code) return hash(self.func_code)
def c_support_code_apply(self, node, name): def c_support_code_apply(self, node, name):
func_code = self.func_code.replace("<<<<NODE_NAME_PLACEHOLDER>>>>",
name)
if hasattr(self, 'check_inputs') and self.check_inputs == False: if hasattr(self, 'check_inputs') and self.check_inputs == False:
return func_code return self.func_code
else: else:
define_macros, undef_macros = self.get_c_macros(node, name) define_macros, undef_macros = self.get_c_macros(node, name)
return os.linesep.join([define_macros, func_code, undef_macros]) return os.linesep.join([define_macros, self.func_code,
undef_macros])
def format_c_function_args(self, inp, out): def format_c_function_args(self, inp, out):
# Generate an string containing the arguments sent to the external C # Generate an string containing the arguments sent to the external C
...@@ -1058,17 +1056,25 @@ class COp(Op): ...@@ -1058,17 +1056,25 @@ class COp(Op):
define_macros += define_template % (macro_name, macro_value) define_macros += define_template % (macro_name, macro_value)
undef_macros += undef_template % macro_name undef_macros += undef_template % macro_name
# Generate a macro to mark code as being apply-specific
define_macros += define_template % ("APPLY_SPECIFIC(str)",
"str##_%s" % name)
undef_macros += undef_template % "APPLY_SPECIFIC"
return define_macros, undef_macros return define_macros, undef_macros
def c_code(self, node, name, inp, out, sub): def c_code(self, node, name, inp, out, sub):
func_name = self.func_name.replace("<<<<NODE_NAME_PLACEHOLDER>>>>", func_name = self.func_name
name)
func_args = self.format_c_function_args(inp, out) func_args = self.format_c_function_args(inp, out)
fail = sub['fail'] fail = sub['fail']
# Generate the code to define/undefine the C macros
define_macros, undef_macros = self.get_c_macros(node, name)
# Generate the C code # Generate the C code
c_code = """ c_code = """
%(define_macros)s
{ {
int result = %(func_name)s(%(func_args)s); int result = %(func_name)s(%(func_args)s);
if (result != 0) if (result != 0)
...@@ -1076,6 +1082,7 @@ class COp(Op): ...@@ -1076,6 +1082,7 @@ class COp(Op):
%(fail)s; %(fail)s;
} }
} }
%(undef_macros)s
""" % locals() """ % locals()
return c_code return c_code
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论