提交 239b6d80 authored 作者: Frédéric Bastien's avatar Frédéric Bastien

Merge pull request #2117 from abergeron/dnn

Add support for subsampling and gradient to GpuDnnConv
...@@ -2,6 +2,7 @@ global-include *.txt ...@@ -2,6 +2,7 @@ global-include *.txt
global-include *.c global-include *.c
global-include *.cu global-include *.cu
global-include *.cuh global-include *.cuh
global-include *.h
global-include *.sh global-include *.sh
global-include *.pkl global-include *.pkl
recursive-include docs recursive-include docs
......
...@@ -193,7 +193,7 @@ def do_setup(): ...@@ -193,7 +193,7 @@ def do_setup():
install_requires=['numpy>=1.5.0', 'scipy>=0.7.2'], install_requires=['numpy>=1.5.0', 'scipy>=0.7.2'],
package_data={ package_data={
'': ['*.txt', '*.rst', '*.cu', '*.cuh', '*.c', '*.sh', '*.pkl', '': ['*.txt', '*.rst', '*.cu', '*.cuh', '*.c', '*.sh', '*.pkl',
'ChangeLog'], '*.h', 'ChangeLog'],
'theano.misc': ['*.sh'] 'theano.misc': ['*.sh']
}, },
scripts=['bin/theano-cache', 'bin/theano-nose', 'bin/theano-test'], scripts=['bin/theano-cache', 'bin/theano-nose', 'bin/theano-test'],
......
import numpy
import theano
from theano.gof.type import * from theano import Op, Apply
from theano.tensor import TensorType
from theano.gof.type import CDataType
# todo: test generic # todo: test generic
class ProdOp(Op):
__props__ = ()
def make_node(self, i):
return Apply(self, [i], [CDataType('void *', 'py_decref')()])
def c_support_code(self):
return """
void py_decref(void *p) {
Py_XDECREF((PyObject *)p);
}
"""
def c_code(self, node, name, inps, outs, sub):
return """
Py_XDECREF(%(out)s);
%(out)s = (void *)%(inp)s;
Py_INCREF(%(inp)s);
""" % dict(out=outs[0], inp=inps[0])
def c_code_cache_version(self):
return (0,)
class GetOp(Op):
__props__ = ()
def make_node(self, c):
return Apply(self, [c], [TensorType('float32', (False,))()])
def c_support_code(self):
return """
void py_decref(void *p) {
Py_XDECREF((PyObject *)p);
}
"""
def c_code(self, node, name, inps, outs, sub):
return """
Py_XDECREF(%(out)s);
%(out)s = (PyArrayObject *)%(inp)s;
Py_INCREF(%(out)s);
""" % dict(out=outs[0], inp=inps[0])
def c_code_cache_version(self):
return (0,)
def test_cdata():
i = TensorType('float32', (False,))()
c = ProdOp()(i)
i2 = GetOp()(c)
# This should be a passthrough function for vectors
f = theano.function([i], i2)
v = numpy.random.randn(9).astype('float32')
v2 = f(v)
assert (v2 == v).all()
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
__docformat__ = "restructuredtext en" __docformat__ = "restructuredtext en"
from theano.compat import PY3
from theano.gof import utils from theano.gof import utils
from theano.gof.utils import MethodNotDefined, object2 from theano.gof.utils import MethodNotDefined, object2
from theano.gof import graph from theano.gof import graph
...@@ -158,7 +160,7 @@ class CLinkerType(CLinkerObject): ...@@ -158,7 +160,7 @@ class CLinkerType(CLinkerObject):
c_extract_code=self.c_extract(name, sub, check_input)) c_extract_code=self.c_extract(name, sub, check_input))
def c_cleanup(self, name, sub): def c_cleanup(self, name, sub):
"""Optional: Return c code to clean up after `c_extract`. """Return c code to clean up after `c_extract`.
This returns C code that should deallocate whatever `c_extract` This returns C code that should deallocate whatever `c_extract`
allocated or decrease the reference counts. Do not decrease allocated or decrease the reference counts. Do not decrease
...@@ -470,3 +472,97 @@ class Generic(SingletonType): ...@@ -470,3 +472,97 @@ class Generic(SingletonType):
return self.__class__.__name__ return self.__class__.__name__
generic = Generic() generic = Generic()
class CDataType(Type):
"""
Represents opaque C data to be passed around. The intent is to
ease passing arbitrary data between ops C code.
"""
def __init__(self, ctype, freefunc=None):
"""
Build a type made to represent a C pointer in theano.
:param ctype: The type of the pointer (complete with the `*`)
:param freefunc: a function to call to free the pointer. This
function must have a `void` return and take a
single pointer argument.
"""
assert isinstance(ctype, basestring)
self.ctype = ctype
if freefunc is not None:
assert isinstance(freefunc, basestring)
self.freefunc = freefunc
def __eq__(self, other):
return (type(self) == type(other) and
self.ctype == other.ctype,
self.freefunc == other.freefunc)
def __hash__(self):
return hash((type(self), self.ctype, self.freefunc))
def filter(self, data, strict=False, allow_downcast=None):
if data is not None:
raise TypeError("only None is valid")
def is_valid_value(self, a):
return a is None
def c_declare(self, name, sub, check_input=True):
return """
%(ctype)s %(name)s;
""" % dict(ctype=self.ctype, name=name)
def c_init(self, name, sub):
return "%(name)s = NULL;" % dict(name=name)
def c_extract(self, name, sub, check_input=True):
if PY3:
s = """
%(name)s = (%(ctype)s)PyCapsule_GetPointer(py_%(name)s, NULL);
if (%(name)s == NULL) %(fail)s
"""
else:
s = """
%(name)s = (%(ctype)s)PyCObject_AsVoidPtr(py_%(name)s);
"""
return s % dict(name=name, ctype=self.ctype, fail=sub['fail'])
def c_sync(self, name, sub):
freefunc = self.freefunc
if freefunc is None:
freefunc = "NULL"
s = """
Py_XDECREF(py_%(name)s);
if (%(name)s == NULL) {
py_%(name)s = Py_None;
Py_INCREF(py_%(name)s);
} else """
if PY3:
s += """{
py_%(name)s = PyCapsule_New((void *)%(name)s, NULL,
(void (*)(void *))%(freefunc)s);
}"""
else:
s += """{
py_%(name)s = PyCObject_FromVoidPtr((void *)%(name)s,
(void (*)(void *))%(freefunc)s);
}"""
if self.freefunc is not None:
s += """
if (py_%(name)s == NULL) { %(freefunc)s(%(name)s); }
"""
return s % dict(name=name, freefunc=freefunc)
def c_cleanup(self, name, sub):
# No need to do anything here since the CObject/Capsule will
# free the data for us when released.
return ""
def c_code_cache_version(self):
return (1,)
def __str__(self):
return "%s{%s}" % (self.__class__.__name__, self.ctype)
差异被折叠。
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论