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

Replaced ifndef-define structure with section markers in C code.

上级 b1247c12
......@@ -740,16 +740,18 @@ C file named vectorTimesVector.c :
.. code-block:: c
// Support code
#ifndef VECTOR_TIMES_VECTOR_SUPPORT_CODE
#define VECTOR_TIMES_VECTOR_SUPPORT_CODE
THEANO_SUPPORT_CODE_SECTION
// Support code function
bool vector_same_shape(PyArrayObject* arr1, PyArrayObject* arr2)
{
return (PyArray_DIMS(arr1)[0] == PyArray_DIMS(arr2)[0]);
}
#endif
// Apply-specific support code
THEANO_APPLY_CODE_SECTION
// Apply-specific support function
void APPLY_SPECIFIC(vector_elemwise_mult)(
DTYPE_INPUT_0* x_ptr, int x_str,
DTYPE_INPUT_1* y_ptr, int y_str,
......@@ -760,7 +762,7 @@ C file named vectorTimesVector.c :
}
}
// Main function
// Apply-specific main function
int APPLY_SPECIFIC(vector_times_vector)(PyArrayObject* input0,
PyArrayObject* input1,
PyArrayObject** output0)
......@@ -918,26 +920,31 @@ 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
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.
Apply-agnostic code should now be defined inside a ``ifndef``-``define``
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
functions and global variables only need to include the name of the
:ref:`Apply` node in their names. To achieve this, the macro
``APPLY_SPECIFIC(str)`` should be used when defining those elements as well as
when referring to them. In the above example, this macro is used when defining
the functions ``vector_elemwise_mult()`` and ``vector_times_vector()`` as well
as when calling function ``vector_elemwise_mult()`` from inside
``vector_times_vector()``.
These two types of support code should each be defined in their own section of
the file, like in the example above. These sections should be delimited by the
markers ``THEANO_SUPPORT_CODE_SECTION`` (to be put on its own line, at the
beginning of the apply-agnostic support code section) and
``THEANO_APPLY_CODE_SECTION`` (to be put on its own line at the beginning of
the apply-specific code section). Moreover, just like in the previous examples
of this tutorial, apply-specific functions and global variables need to
include the name of the :ref:`Apply` node in their names. To achieve this,
the macro ``APPLY_SPECIFIC(str)`` should be used when defining those elements
as well as when referring to them. In the above example, this macro is used
when defining the functions ``vector_elemwise_mult()`` and
``vector_times_vector()`` as well as when calling function
``vector_elemwise_mult()`` from inside ``vector_times_vector()``.
:note:
The macro ``APPLY_SPECIFIC(str)`` should only ever be used for
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
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
apply-specific. Otherwise, it is apply-agnostic.
The rules for knowing if a piece of code should be put in the apply-agnostic
or the apply-specific support code section of the file are simple. If it uses
any of the macros defined by the class ``COp`` then it is apply-specific and
goes in the corresponding section. If it calls any apply-specific code then
it is apply-specific. Otherwise, it is apply-agnostic and goes in the
apply-agnostic support code section.
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
......
......@@ -992,21 +992,85 @@ class COp(Op):
self.func_file = func_file
self.func_name = func_name
# Load the func
# Define the markers that can be used to delimit sections in the
# external C code
self.support_code_marker = "THEANO_SUPPORT_CODE_SECTION"
self.apply_code_marker = "THEANO_APPLY_CODE_SECTION"
self.c_code_markers = [self.support_code_marker,
self.apply_code_marker]
# Load the external C code
f = open(self.func_file, "r")
self.func_code = f.read()
f.close()
# Separate the contents of the file in sections and validate that at
# lest one of the necessary code sections has been defined
self.code_sections = self.parse_external_c_code(self.func_code)
if sum([marker in self.code_sections.keys()
for marker in self.c_code_markers]) == 0:
raise(RuntimeError, "The provided C implementation does not "
"define a support code section or a support code apply "
"section.")
def parse_external_c_code(self, code):
# Obtain the positions of the C code markers used in the C code
positions = [(code.index(marker), marker)
for marker in self.c_code_markers if marker in code]
# Go over the markers in their order of occurence and extract
# the C code they concern
positions.sort()
code_sections = {}
for i in range(len(positions)):
marker_start, marker = positions[i]
if i < len(positions) - 1:
# This is not the last section in the code : extract the code
# between the beginning of the current marker and the
# beginning of the next one.
next_marker_start = positions[i+1][0]
section = code[marker_start: next_marker_start]
else:
# This is the last section in the code : extract the remaining
# C code
section = code[marker_start:]
cleaned_section = section.replace(marker, "")
code_sections[marker] = cleaned_section
return code_sections
def c_code_cache_version(self):
return hash(self.func_code)
def c_support_code(self):
if self.support_code_marker in self.code_sections:
return self.code_sections[self.support_code_marker]
else:
return ""
def c_support_code_apply(self, node, name):
if hasattr(self, 'check_inputs') and self.check_inputs == False:
return self.func_code
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:
define_macros, undef_macros = self.get_c_macros(node, name)
return os.linesep.join([define_macros, self.func_code,
undef_macros])
return ""
def format_c_function_args(self, inp, out):
# Generate an string containing the arguments sent to the external C
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论