Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
P
pytensor
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
testgroup
pytensor
Commits
21dddad9
提交
21dddad9
authored
9月 26, 2014
作者:
pl
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Fixed typos and removed trailing whitespaces.
上级
b970f9b8
显示空白字符变更
内嵌
并排
正在显示
1 个修改的文件
包含
24 行增加
和
40 行删除
+24
-40
extending_theano_c.txt
doc/tutorial/extending_theano_c.txt
+24
-40
没有找到文件。
doc/tutorial/extending_theano_c.txt
浏览文件 @
21dddad9
...
@@ -9,7 +9,7 @@ This tutorial covers how to extend Theano with an op that offers a C
...
@@ -9,7 +9,7 @@ This tutorial covers how to extend Theano with an op that offers a C
implementation. It does not cover ops that run on a GPU but it does introduce
implementation. It does not cover ops that run on a GPU but it does introduce
many elements and concepts which are relevant for GPU ops. This tutorial is
many elements and concepts which are relevant for GPU ops. This tutorial is
aimed at individuals who already know how to extend Theano (see tutorial
aimed at individuals who already know how to extend Theano (see tutorial
:ref:`extending_theano`) by adding a new op with a
p
ython implementation
:ref:`extending_theano`) by adding a new op with a
P
ython implementation
and will only cover the additional knowledge required to also produce ops
and will only cover the additional knowledge required to also produce ops
with C implementations.
with C implementations.
...
@@ -25,7 +25,7 @@ vector by a scalar.
...
@@ -25,7 +25,7 @@ vector by a scalar.
Python C-API
Python C-API
============
============
Python provides a C-API to allow the manipulation of
p
ython objects from
Python provides a C-API to allow the manipulation of
P
ython objects from
C code. In this API, all classes that represent Python objects are descendants
C code. In this API, all classes that represent Python objects are descendants
of the class PyObject. This class is essentially a wrapper; an instance of
of the class PyObject. This class is essentially a wrapper; an instance of
PyObject contains a pointer to another object as well as a reference count
PyObject contains a pointer to another object as well as a reference count
...
@@ -44,7 +44,7 @@ Reference counting is a mechanism for keeping track, for an object, of
...
@@ -44,7 +44,7 @@ Reference counting is a mechanism for keeping track, for an object, of
the number of references to it held by other entities. This mechanism is often
the number of references to it held by other entities. This mechanism is often
used for purposes of garbage collecting because it allows to easily see if
used for purposes of garbage collecting because it allows to easily see if
an object is still being used by other entities. When the reference count
an object is still being used by other entities. When the reference count
for an object drops to 0, it means it is not used by any
anyone
and can
for an object drops to 0, it means it is not used by any
one any longer
and can
be safely deleted.
be safely deleted.
PyObjects implement reference counting and the Python C-API defines a number
PyObjects implement reference counting and the Python C-API defines a number
...
@@ -86,7 +86,7 @@ NumPy C-API
...
@@ -86,7 +86,7 @@ NumPy C-API
The NumPy library provides a C-API to allow users to create, access and
The NumPy library provides a C-API to allow users to create, access and
manipulate NumPy arrays from within their own C routines. NumPy's ndarrays
manipulate NumPy arrays from within their own C routines. NumPy's ndarrays
are used extensively inside
t
heano and so extending Theano with a C op will
are used extensively inside
T
heano and so extending Theano with a C op will
require interaction with the NumPy C-API.
require interaction with the NumPy C-API.
This sections covers the API's elements that are often required to write code
This sections covers the API's elements that are often required to write code
...
@@ -234,18 +234,18 @@ The following functions allow the creation and copy of NumPy arrays :
...
@@ -234,18 +234,18 @@ The following functions allow the creation and copy of NumPy arrays :
Function
s the C Op needs to define
Method
s the C Op needs to define
================================
==
================================
There is a key difference between an
d
op defining a Python implementation for
There is a key difference between an op defining a Python implementation for
its computation and defining a C implementation. In the case of a Python
its computation and defining a C implementation. In the case of a Python
implementation, the op defines a function perform() which executes the
implementation, the op defines a function perform() which executes the
required
p
ython code to realize the op. In the case of a C implementation,
required
P
ython code to realize the op. In the case of a C implementation,
however, the op does **not** define a function that will execute the C code; it
however, the op does **not** define a function that will execute the C code; it
instead defines functions that will **return** the C code to the caller.
instead defines functions that will **return** the C code to the caller.
This is because calling C code from Python code comes with a significant
This is because calling C code from Python code comes with a significant
overhead. If every op was responsible for executing it
'
s own C code, every
overhead. If every op was responsible for executing its own C code, every
time a Theano function was called, this overhead would occur as many times
time a Theano function was called, this overhead would occur as many times
as the number of ops with C implementations in the function's computational
as the number of ops with C implementations in the function's computational
graph.
graph.
...
@@ -254,13 +254,12 @@ To maximize performance, Theano instead requires the C ops to simply return
...
@@ -254,13 +254,12 @@ To maximize performance, Theano instead requires the C ops to simply return
the code needed for their execution and takes upon itself the task of
the code needed for their execution and takes upon itself the task of
organizing, linking and compiling the code from the various ops. Through this,
organizing, linking and compiling the code from the various ops. Through this,
Theano is able to minimize the number of times C code is called from Python
Theano is able to minimize the number of times C code is called from Python
code by maximizing the amount of computation that is done every time C code
code.
is called from Python.
The following is a very
crud
e example to illustrate how it's possible to
The following is a very
simpl
e example to illustrate how it's possible to
obtain performance gains with this process. Suppose you need to execute,
obtain performance gains with this process. Suppose you need to execute,
from Python code, 10 different ops, each one having a C implementation. If
from Python code, 10 different ops, each one having a C implementation. If
each op was responsible for executing it
'
s own C code, the overhead of
each op was responsible for executing its own C code, the overhead of
calling C code from Python code would occur 10 times. Consider now the case
calling C code from Python code would occur 10 times. Consider now the case
where the ops instead return the C code for their execution. You could get
where the ops instead return the C code for their execution. You could get
the C code from each op and then define your own C module that would call
the C code from each op and then define your own C module that would call
...
@@ -274,20 +273,20 @@ code. This allows for faster compilation times.
...
@@ -274,20 +273,20 @@ code. This allows for faster compilation times.
See :ref:`cop` for the full documentation of the various methods of the
See :ref:`cop` for the full documentation of the various methods of the
class Op that are related to the C implementation. Of particular interest are:
class Op that are related to the C implementation. Of particular interest are:
* The
functions c_libraries() and c_lib_dirs() to allow your op to use
* The
methods c_libraries() and c_lib_dirs() to allow your op to use
external libraries.
external libraries.
* The
function
c_code_cleanup() to specify how the op should clean up
* The
method
c_code_cleanup() to specify how the op should clean up
what it has allocated during its execution.
what it has allocated during its execution.
* The
function
s c_init_code() and c_init_code_apply() to specify code
* The
method
s c_init_code() and c_init_code_apply() to specify code
that should be executed once when the module is initialized, before
that should be executed once when the module is initialized, before
anything else is executed.
anything else is executed.
* The
function
s c_compile_args() and c_no_compile_args() to specify
* The
method
s c_compile_args() and c_no_compile_args() to specify
requirements regarding how the op's C code should be compiled.
requirements regarding how the op's C code should be compiled.
This section
s describes the functions c_code(), c_support_code() and
This section
describes the methods c_code(), c_support_code() and
c_code_cache_version() because they are the ones that are most commonly
c_code_cache_version() because they are the ones that are most commonly
used.
used.
...
@@ -304,13 +303,13 @@ used.
...
@@ -304,13 +303,13 @@ used.
as the op has inputs. Each string contains the name of the C variable
as the op has inputs. Each string contains the name of the C variable
to which the corresponding input has been assigned. For example, the name
to which the corresponding input has been assigned. For example, the name
of the C variable representing the first input of the op is given by
of the C variable representing the first input of the op is given by
``input_names[0]``. You should therefore use this name
to interact
in your
``input_names[0]``. You should therefore use this name in your
C code to interact with that variable. ``output_names`` is used
C code to interact with that variable. ``output_names`` is used
identically to ``input_names``, but for the ops' outputs.
identically to ``input_names``, but for the ops' outputs.
Finally, `sub` is a dictionary of extras parameters to the c_code
Finally, `sub` is a dictionary of extras parameters to the c_code
method. Among other things, it contains ``sub['fail']`` which is a string
method. Among other things, it contains ``sub['fail']`` which is a string
of C code that you should execute (after ensuring that a
p
ython exception
of C code that you should execute (after ensuring that a
P
ython exception
is set) if your C code needs to raise an exception.
is set) if your C code needs to raise an exception.
:note:
:note:
...
@@ -329,9 +328,9 @@ used.
...
@@ -329,9 +328,9 @@ used.
Returns a tuple of integers representing the version of the C code in this
Returns a tuple of integers representing the version of the C code in this
op. Ex : (1, 4, 0) for version 1.4.0
op. Ex : (1, 4, 0) for version 1.4.0
This tuple is used by
t
heano to cache the compiled C code for this op. As
This tuple is used by
T
heano to cache the compiled C code for this op. As
such, the return value **MUST
be CHANGED** everytime the C code is altered or
such, the return value **MUST
BE CHANGED** every time the C code is altered
else Theano will disregard the change in the code and simply load a
or
else Theano will disregard the change in the code and simply load a
previous version of the op from the cache. If you want to avoid caching of
previous version of the op from the cache. If you want to avoid caching of
the C code of this op, return an empty tuple or do not implement this
the C code of this op, return an empty tuple or do not implement this
method.
method.
...
@@ -399,9 +398,6 @@ storage with the right shape and number of dimensions.
...
@@ -399,9 +398,6 @@ storage with the right shape and number of dimensions.
return gof.Apply(self, [x, y], [output_var])
return gof.Apply(self, [x, y], [output_var])
def __str__(self):
return self.__class__.__name__
def c_code_cache_version(self):
def c_code_cache_version(self):
return (1, 0)
return (1, 0)
...
@@ -419,22 +415,10 @@ storage with the right shape and number of dimensions.
...
@@ -419,22 +415,10 @@ storage with the right shape and number of dimensions.
fail = sub['fail']
fail = sub['fail']
c_code = """
c_code = """
// Validate the inputs
if (PyArray_NDIM(%(x)s) != 1)
{
PyErr_SetString(PyExc_ValueError, "x is not a 1d tensor");
%(fail)s;
}
if (PyArray_NDIM(%(y)s) != 0)
{
PyErr_SetString(PyExc_ValueError, "y is not a scalar");
%(fail)s;
}
// Validate that the output storage exists and has the same
// Validate that the output storage exists and has the same
// dimension as x.
// dimension as x.
if (
(NULL == %(z)s) || PyArray_NDIM(%(z)s) != 1
||
if (
NULL == %(z)s
||
(PyArray_DIMS(%(x)s)[0] != PyArray_DIMS(%(z)s)[0])
)
PyArray_DIMS(%(x)s)[0] != PyArray_DIMS(%(z)s)[0]
)
{
{
/* Reference received to invalid output variable.
/* Reference received to invalid output variable.
Decrease received reference's ref count and allocate new
Decrease received reference's ref count and allocate new
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论