提交 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 : ...@@ -740,16 +740,18 @@ C file named vectorTimesVector.c :
.. code-block:: c .. code-block:: c
// Support code THEANO_SUPPORT_CODE_SECTION
#ifndef VECTOR_TIMES_VECTOR_SUPPORT_CODE
#define VECTOR_TIMES_VECTOR_SUPPORT_CODE // Support code function
bool vector_same_shape(PyArrayObject* arr1, PyArrayObject* arr2) bool vector_same_shape(PyArrayObject* arr1, PyArrayObject* arr2)
{ {
return (PyArray_DIMS(arr1)[0] == PyArray_DIMS(arr2)[0]); 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)( 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,
...@@ -760,7 +762,7 @@ C file named vectorTimesVector.c : ...@@ -760,7 +762,7 @@ C file named vectorTimesVector.c :
} }
} }
// Main function // Apply-specific main function
int APPLY_SPECIFIC(vector_times_vector)(PyArrayObject* input0, int APPLY_SPECIFIC(vector_times_vector)(PyArrayObject* input0,
PyArrayObject* input1, PyArrayObject* input1,
PyArrayObject** output0) PyArrayObject** output0)
...@@ -918,26 +920,31 @@ wasn't apply-specific was simply defined in the ``c_support_code()`` method. ...@@ -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 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`` These two types of support code should each be defined in their own section of
structure (like the function ``vector_same_shape()`` in the example above) to the file, like in the example above. These sections should be delimited by the
ensure that it is only defined once. On the other hand, apply-specific markers ``THEANO_SUPPORT_CODE_SECTION`` (to be put on its own line, at the
functions and global variables only need to include the name of the beginning of the apply-agnostic support code section) and
:ref:`Apply` node in their names. To achieve this, the macro ``THEANO_APPLY_CODE_SECTION`` (to be put on its own line at the beginning of
``APPLY_SPECIFIC(str)`` should be used when defining those elements as well as the apply-specific code section). Moreover, just like in the previous examples
when referring to them. In the above example, this macro is used when defining of this tutorial, apply-specific functions and global variables need to
the functions ``vector_elemwise_mult()`` and ``vector_times_vector()`` as well include the name of the :ref:`Apply` node in their names. To achieve this,
as when calling function ``vector_elemwise_mult()`` from inside the macro ``APPLY_SPECIFIC(str)`` should be used when defining those elements
``vector_times_vector()``. 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: :note:
The macro ``APPLY_SPECIFIC(str)`` 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 put in the apply-agnostic
or not are simple; if it uses any of the macros defined by the class ``COp`` or the apply-specific support code section of the file are simple. If it uses
then it is apply-specific, if it calls any apply-specific code then it is any of the macros defined by the class ``COp`` then it is apply-specific and
apply-specific. Otherwise, it is apply-agnostic. 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 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 because it uses none of the macros defined by the class ``COp`` and it doesn't
......
...@@ -992,22 +992,86 @@ class COp(Op): ...@@ -992,22 +992,86 @@ class COp(Op):
self.func_file = func_file self.func_file = func_file
self.func_name = func_name 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") f = open(self.func_file, "r")
self.func_code = f.read() self.func_code = f.read()
f.close() 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): def c_code_cache_version(self):
return hash(self.func_code) 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): 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: if hasattr(self, 'check_inputs') and self.check_inputs == False:
return self.func_code return apply_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, self.func_code, return os.linesep.join([define_macros, apply_code,
undef_macros]) undef_macros])
else:
return ""
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
# function. The argstring will be of format : # function. The argstring will be of format :
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论