提交 5f522361 authored 作者: Arnaud Bergeron's avatar Arnaud Bergeron

Add a more complex example and remove section about CDataType since it doesn't work.

上级 aaf18388
...@@ -8,6 +8,10 @@ The Op params is a facility to pass some runtime parameters to the ...@@ -8,6 +8,10 @@ The Op params is a facility to pass some runtime parameters to the
code of an op without modifying it. It can enable a single instance code of an op without modifying it. It can enable a single instance
of C code to serve different needs and therefore reduce compilation. of C code to serve different needs and therefore reduce compilation.
The code enables you to pass a single object, but it can be a struct
or python object with multiple values if you have more than one value
to pass.
We will first introduce the parts involved in actually using this We will first introduce the parts involved in actually using this
functionality and then present a simple working example. functionality and then present a simple working example.
...@@ -15,23 +19,19 @@ The params type ...@@ -15,23 +19,19 @@ The params type
---------------- ----------------
You can either reuse an existing type such as :class:`Generic` or You can either reuse an existing type such as :class:`Generic` or
:class:`CDataType`, or create your own. create your own.
Using a python object for your op parameters (:class:`Generic`) can be Using a python object for your op parameters (:class:`Generic`) can be
annoying to access from C code since you would have to go through the annoying to access from C code since you would have to go through the
Python-C API for all accesses. Python-C API for all accesses.
Conversly, using a C struct (:class:`CDataType`) makes it complicated
to set values through python code, forcing you to go through ctypes or
other similar module.
Making a purpose-built class may require more upfront work, but can Making a purpose-built class may require more upfront work, but can
pay off if you reuse the type for a lot of Ops, by making it easier to pay off if you reuse the type for a lot of Ops, by not having to re-do
manipulate from python and C. all of the python manipulation.
Defining a params type Defining a params type
~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~
.. note:: .. note::
...@@ -67,16 +67,16 @@ attribute :attr:`params_type` to an instance of your params Type. ...@@ -67,16 +67,16 @@ attribute :attr:`params_type` to an instance of your params Type.
.. note:: .. note::
If you want to have multiple parameters you have to bundle those If you want to have multiple parameters you have to bundle those
inside a single object (or C struct) and use that as the params inside a single object and use that as the params type. Multiple
type. Multiple types are not supported. types are not supported.
For example if we decide to use a pointer to an int as the params the For example if we decide to use an int as the params the following
following would be appropriate: would be appropriate:
.. code-block:: python .. code-block:: python
class MyOp(Op): class MyOp(Op):
params_type = CDataType('int') params_type = Generic()
After that you need to define a :meth:`get_params` method on your After that you need to define a :meth:`get_params` method on your
class with the following signature: class with the following signature:
...@@ -159,3 +159,57 @@ the params type. ...@@ -159,3 +159,57 @@ the params type.
.. testoutput:: .. testoutput::
:hide: :hide:
A more complex example
----------------------
This is a more complex example which actually passes multiple values. It does a linear combination of two values using floating point weights.
.. testcode::
from theano import Op
from theano.gof.type import Generic
from theano.scalar import as_scalar
class ab(object):
def __init__(self, alpha, beta):
self.alpha = alpha
self.beta = beta
class Mix(Op):
params_type = Generic()
__props__ = ('alpha', 'beta')
def __init__(self, alpha, beta):
self.alpha = alpha
self.beta = beta
def get_params(self, node):
return ab(alpha=self.alpha, beta=self.beta)
def make_node(self, x, y):
x = as_scalar(x)
y = as_scalar(y)
return Apply(self, [x, y], [x.type()]
def c_code(self, node, name, inputs, outputs, sub):
return """
PyObject *tmp;
double a, b;
tmp = PyObject_GetAttrString(%(p)s, "alpha");
if (tmp == NULL)
%(fail)s
a = PyFloat_AsDouble(tmp);
Py_DECREF(tmp);
tmp = PyObject_GetAttrString(%(p)s, "beta");
if (tmp == NULL)
%(fail)s
b = PyFloat_AsDouble(tmp);
Py_DECREF(tmp);
%(z)s = a* %(x)s + b * %(y)s;
""" % dict(p=sub['params'], z=outputs[0], x=inputs[0], y=inputs[1])
.. testoutput::
:hide:
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论