提交 50ca43a3 authored 作者: James Bergstra's avatar James Bergstra

merge

...@@ -38,11 +38,13 @@ There are less methods to define for an Op than for a Type: ...@@ -38,11 +38,13 @@ There are less methods to define for an Op than for a Type:
*Default:* The default behavior is to do nothing. *Default:* The default behavior is to do nothing.
.. function:: c_compile_args() .. function:: c_compile_args()
c_no_compile_args()
c_headers() c_headers()
c_libraries() c_libraries()
c_support_code() c_support_code()
Allows you to specify headers, libraries, special g++ arguments or Allows you to specify headers, libraries,
special g++ arguments to add/exclude or
helper functions/structs that the type needs. See :ref:`op`. helper functions/structs that the type needs. See :ref:`op`.
......
...@@ -75,11 +75,13 @@ the most important ones: ...@@ -75,11 +75,13 @@ the most important ones:
decrease the appropriate reference counts. decrease the appropriate reference counts.
.. function:: c_compile_args() .. function:: c_compile_args()
c_no_compile_args()
c_headers() c_headers()
c_libraries() c_libraries()
c_support_code() c_support_code()
Allows you to specify headers, libraries, special g++ arguments or Allows you to specify headers, libraries,
special g++ arguments to add/exclude or
helper functions/structs that the type needs. See :ref:`type`. helper functions/structs that the type needs. See :ref:`type`.
......
...@@ -260,7 +260,7 @@ Glossary of terminology ...@@ -260,7 +260,7 @@ Glossary of terminology
* making :term:`Apply` instances, which mean "apply this TOI to some particular inputs" (via the ``make_node``), * making :term:`Apply` instances, which mean "apply this TOI to some particular inputs" (via the ``make_node``),
* performing the calculation of outputs from given inputs (via the ``perform``), * performing the calculation of outputs from given inputs (via the ``perform``),
* producing c code to perform calculation of outputs from inputs (via ``c_code, c_code_cleanup, c_support_code, c_headers, c_libraries, c_compile_args``) * producing c code to perform calculation of outputs from inputs (via ``c_code, c_code_cleanup, c_support_code, c_headers, c_libraries, c_compile_args, c_no_compile_args``)
* [optionally] building gradient-calculating graphs (via ``grad``). * [optionally] building gradient-calculating graphs (via ``grad``).
See :ref:`intro_to_ops`. See :ref:`intro_to_ops`.
......
...@@ -163,7 +163,12 @@ class In(SymbolicInput): ...@@ -163,7 +163,12 @@ class In(SymbolicInput):
mutable=None, strict=False, autoname=True, mutable=None, strict=False, autoname=True,
implicit=None): implicit=None):
if implicit is None: if implicit is None:
implicit = isinstance(value, gof.Container) # TODO Having a default value being a Variable only makes sense
# if this is a SharedVariable. This should be changed once shared
# variables are part of Theano instead of living in a separate
# repository.
implicit = (isinstance(value, gof.Container) or
isinstance(value, gof.Variable))
super(In, self).__init__(variable, name, update, mutable, strict, super(In, self).__init__(variable, name, update, mutable, strict,
autoname, implicit = implicit) autoname, implicit = implicit)
self.value = value self.value = value
......
...@@ -678,6 +678,23 @@ def test_method_mode(): ...@@ -678,6 +678,23 @@ def test_method_mode():
assert m.h.maker.mode == m.g.maker.mode assert m.h.maker.mode == m.g.maker.mode
assert numpy.all(m.f([1,2]) == m.g([1,2])) assert numpy.all(m.f([1,2]) == m.g([1,2]))
def test_method_implicit_ticket_384():
"""
Ensure it is not possible to accidentally overwrite module variables
added as implicit inputs.
"""
M = Module()
M.x = T.scalar()
M.f = Method([M.x], M.x * 3)
m = M.make()
m.f(0)
try:
m.f(0, 0)
assert False
except TypeError, e:
if not str(e).startswith('Tried to provide value for implicit input'):
raise
def test_pickle(): def test_pickle():
"""Test that a module can be pickled""" """Test that a module can be pickled"""
M = Module() M = Module()
......
...@@ -526,10 +526,23 @@ class CLinker(link.Linker): ...@@ -526,10 +526,23 @@ class CLinker(link.Linker):
This might contain duplicates. This might contain duplicates.
""" """
ret = [] ret = ["-O3", "-w"]#-w means supress all warnings
# this is the param the -ffast-math activate. I put the explicitly as FillMissing must disable "-ffinite-math-only". Putting -ffast-math would make it disable all other parameter at the same time.
ret += ["-fno-math-errno", "-funsafe-math-optimizations",
"-fno-signaling-nans", "-fcx-limited-range",
"-fno-rounding-math", "-ffinite-math-only"]
for x in [y.type for y in self.variables] + [y.op for y in self.node_order]: for x in [y.type for y in self.variables] + [y.op for y in self.node_order]:
try: ret += x.c_compile_args() try: ret += x.c_compile_args()
except utils.MethodNotDefined: pass except utils.MethodNotDefined: pass
ret=list(set(ret))#to remove duplicate
for x in [y.type for y in self.variables] + [y.op for y in self.node_order]:
try:
for i in x.c_no_compile_args():
try:
ret.remove(i)
except ValueError:
pass# in case the value is not there
except utils.MethodNotDefined: pass
return ret return ret
def headers(self): def headers(self):
...@@ -703,22 +716,7 @@ class CLinker(link.Linker): ...@@ -703,22 +716,7 @@ class CLinker(link.Linker):
instantiate.customize.add_support_code(support_code) instantiate.customize.add_support_code(support_code)
instantiate.customize.add_support_code(self.struct_code) instantiate.customize.add_support_code(self.struct_code)
instantiate.customize.add_support_code(static) instantiate.customize.add_support_code(static)
for extra_arg in (
"-O3",
# "-fno-signaling-nans",
#"-fno-finite-math-only",
#"-fmath-errno", "-fno-unsafe-math-optimizations", "-fno-finite-math-only", "-frounding-math", "-fsignaling-nans","-fno-cx-limited-range","-fno-fast-math",
"-ffast-math",
#"-fno-finite-math-only",
# "-fno-signaling-nans",
#"-fmath-errno", "-fno-unsafe-math-optimizations", "-fno-finite-math-only", "-frounding-math", "-fsignaling-nans","-fno-cx-limited-range","-fno-fast-math",
#"-fprefetch-loop-arrays",
#"-ftree-vect-loop-version",
#"-ftree-loop-optimize",
#"-ftree-vectorize",
"-w" #-w means supress all warnings
):
instantiate.customize.add_extra_compile_arg(extra_arg)
for arg in self.compile_args(): for arg in self.compile_args():
instantiate.customize.add_extra_compile_arg(arg) instantiate.customize.add_extra_compile_arg(arg)
for header in self.headers(): for header in self.headers():
......
...@@ -97,6 +97,25 @@ class CLinkerOp(object): ...@@ -97,6 +97,25 @@ class CLinkerOp(object):
raise utils.MethodNotDefined('%s.c_compile_args' \ raise utils.MethodNotDefined('%s.c_compile_args' \
% self.__class__.__name__) % self.__class__.__name__)
def c_no_compile_args(self):
"""Optional: Return a list of incompatible gcc compiler arguments.
We will remove those arguments from the command line of gcc. So if
another Op adds a compile arg in the graph that is incompatible
with this Op, the incompatible arg will not be used.
Useful for instance to remove -ffast-math.
EXAMPLE
WRITEME
:Exceptions:
- `MethodNotDefined`: the subclass does not override this method
"""
raise utils.MethodNotDefined('%s.c_no_compile_args' \
% self.__class__.__name__)
def c_headers(self): def c_headers(self):
"""Optional: Return a list of header files that must be included to compile the C code. """Optional: Return a list of header files that must be included to compile the C code.
......
...@@ -148,6 +148,24 @@ class CLinkerType(object): ...@@ -148,6 +148,24 @@ class CLinkerType(object):
""" """
raise MethodNotDefined("c_compile_args", type(self), self.__class__.__name__) raise MethodNotDefined("c_compile_args", type(self), self.__class__.__name__)
def c_no_compile_args(self):
"""Optional: Return a list of incompatible gcc compiler arguments.
We will remove those arguments from the command line of gcc. So if
another Op adds a compile arg in the graph that is incompatible
with this Op, the incompatible arg will not be used.
Useful for instance to remove -ffast-math.
EXAMPLE
WRITEME
:Exceptions:
- `MethodNotDefined`: the subclass does not override this method
"""
raise MethodNotDefined("c_no_compile_args", type(self), self.__class__.__name__)
def c_headers(self): def c_headers(self):
"""Optional: Return a list of header files required by code returned by """Optional: Return a list of header files required by code returned by
this class. this class.
......
...@@ -118,7 +118,11 @@ class ConvOp(Op): ...@@ -118,7 +118,11 @@ class ConvOp(Op):
for im0 in range(self.imshp[0]): for im0 in range(self.imshp[0]):
zz[b,n,...] += _convolve2d(\ zz[b,n,...] += _convolve2d(\
img2d[b,im0,...], filtersflipped[n,im0,...],1,val, bval, 0) img2d[b,im0,...], filtersflipped[n,im0,...],1,val, bval, 0)
zz = zz[:,:,0::self.dx,0::self.dy] #We copy it to remove the Stride mismatch warning from DEBUG_MODE.
#The copy make that we return an object with the same stride as the c version.
#The copy don't affect the performence during our experience as in that case we
#execute the c version which is much faster.
zz = zz[:,:,0::self.dx,0::self.dy].copy()
z[0]=zz z[0]=zz
...@@ -181,6 +185,7 @@ class ConvOp(Op): ...@@ -181,6 +185,7 @@ class ConvOp(Op):
dw = ConvOp(imshp, kshp, nkern, bsize, 1,1, output_mode='valid', dw = ConvOp(imshp, kshp, nkern, bsize, 1,1, output_mode='valid',
unroll_batch=un_b, unroll_kern=un_k)(img,filters) unroll_batch=un_b, unroll_kern=un_k)(img,filters)
assert (dw.owner.op.outshp==self.kshp).all()
if self.out_mode == 'valid': if self.out_mode == 'valid':
# before DimShuffle, dw is of shape visdim x nkern x kshp[0] x kshp[1] # before DimShuffle, dw is of shape visdim x nkern x kshp[0] x kshp[1]
dw = tensor.DimShuffle(dw.broadcastable, (1,0,2,3))(dw) dw = tensor.DimShuffle(dw.broadcastable, (1,0,2,3))(dw)
......
...@@ -725,8 +725,14 @@ class Canonizer(gof.LocalOptimizer): ...@@ -725,8 +725,14 @@ class Canonizer(gof.LocalOptimizer):
return getattr(self, 'name', 'Canonizer(%s, %s, %s)' % (self.main, self.inverse, self.reciprocal)) return getattr(self, 'name', 'Canonizer(%s, %s, %s)' % (self.main, self.inverse, self.reciprocal))
def mul_calculate(num, denum, aslist = False): def mul_calculate(num, denum, aslist=False):
v = reduce(N.multiply, num, 1.0) / reduce(N.multiply, denum, 1.0) if not num and not denum:
# Smallest 1 possible.
return [] if aslist else N.int8(1)
# Make sure we do not accidently upcast data types.
first = num[0] if num else denum[0]
one = N.asarray(first).dtype.type(1)
v = reduce(N.multiply, num, one) / reduce(N.multiply, denum, one)
if aslist: if aslist:
if N.all(v == 1): if N.all(v == 1):
return [] return []
......
...@@ -57,9 +57,13 @@ class test_dimshuffle_lift(unittest.TestCase): ...@@ -57,9 +57,13 @@ class test_dimshuffle_lift(unittest.TestCase):
x, y, z = inputs([False]*1, [False]*2, [False]*3) x, y, z = inputs([False]*1, [False]*2, [False]*3)
e = x + y + z e = x + y + z
g = Env([x, y, z], [e]) g = Env([x, y, z], [e])
self.failUnless(str(g) == "[add(InplaceDimShuffle{x,0,1}(add(InplaceDimShuffle{x,0}(x), y)), z)]", str(g)) self.failUnless(str(g) == ("[Elemwise{add,no_inplace}("
"InplaceDimShuffle{x,0,1}(Elemwise{add,no_inplace}"
"(InplaceDimShuffle{x,0}(x), y)), z)]"), str(g))
dimshuffle_lift.optimize(g) dimshuffle_lift.optimize(g)
self.failUnless(str(g) == "[add(add(InplaceDimShuffle{x,x,0}(x), InplaceDimShuffle{x,0,1}(y)), z)]", str(g)) self.failUnless(str(g) == ("[Elemwise{add,no_inplace}(Elemwise"
"{add,no_inplace}(InplaceDimShuffle{x,x,0}(x), InplaceDimShuffle"
"{x,0,1}(y)), z)]"), str(g))
def test_add_canonizer_problem0(): def test_add_canonizer_problem0():
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论