提交 f7f657ad authored 作者: Frederic Bastien's avatar Frederic Bastien

new version of floatX to allow to test both floatX=float{32,64} at the same time.

added floatX doc.
上级 23a061f4
.. _floatX:
========================
Special data type floatX
========================
Intro
=====
Their is a special data type called floatX. It is not a real datatype. It is never present in the theano graph, but their exist constructor and function that will change the floatX to float32 or float64(default) in your graph. You can change the value of floatX when you start the execution of python by setting the environement variables THEANO_GPU=floatX=float{32,64}(case sensitive). You can have the value of floatX with:
import theano.config as config
config.floatX
This can help to have the same code run on the cpu in float64 and let it run on the gpu in float32. float32 is the only datatype that is currently supported on the gpu. This can give different result due to rounding error. This option help to compare those difference.
Also, on the cpu, float32 are twice as fast as float64.
Their exist helper function in theano.floatx that simplify using this
Here is the list of fonction that create/accept tensor of floatX. They are all variant of function that already exist for other datatype.
theano.scalar.Scalar.__init__(dtype)
theano.scalar.floatX
theano.floatx.xscalar
theano.floatx.xvector
theano.floatx.xmatrix
theano.floatx.xrow
theano.floatx.xcol
theano.floatx.xtensor3
theano.floatx.xtensor4
theano.tensor.cast(TensorVariable, dtype)
TensorType.__init__(dtype, broadcastable, name = None, shape=None)
HINT: linear algorythm are less affected by the different precision then non-linear one.
use numpy.asarray(x,dtype=config.floatX) to cast numpy array to floatX
numpy.asarray(x,dtype=config.floatX) warn copy only if needed.
WARNING: theano.floatx.set_floatX() exist for our test. Don't use it for something else. If you do, it will make code hard to read and it is a sign that their is something better for you then floatX.
...@@ -32,3 +32,4 @@ Now we're ready for the tour: ...@@ -32,3 +32,4 @@ Now we're ready for the tour:
examples examples
module module
tools tools
floatX
...@@ -59,7 +59,8 @@ import scalar ...@@ -59,7 +59,8 @@ import scalar
import sparse import sparse
import gradient import gradient
import gof import gof
import floatx
floatx.set_floatX()
## import scalar_opt ## import scalar_opt
......
...@@ -10,7 +10,6 @@ default_={ ...@@ -10,7 +10,6 @@ default_={
'lib.amdlibm':False, 'lib.amdlibm':False,
'op.set_flops':False,#currently used only in ConvOp. The profile mode will print the flops/s for the op. 'op.set_flops':False,#currently used only in ConvOp. The profile mode will print the flops/s for the op.
'nvcc.fastmath':False, 'nvcc.fastmath':False,
'scalar.floatX':'float64',
'gpuelemwise.sync':True, #when true, wait that the gpu fct finished and check it error code. 'gpuelemwise.sync':True, #when true, wait that the gpu fct finished and check it error code.
} }
...@@ -44,6 +43,24 @@ THEANO_DEBUGMODE_CHECK_STRIDES = bool(int(os.getenv('THEANO_DEBUGMODE_CHECK_STRI ...@@ -44,6 +43,24 @@ THEANO_DEBUGMODE_CHECK_STRIDES = bool(int(os.getenv('THEANO_DEBUGMODE_CHECK_STRI
THEANO_FLAGS=os.getenv("THEANO_FLAGS","") THEANO_FLAGS=os.getenv("THEANO_FLAGS","")
def parse_env_flags(flags, name , default_value=None):
#The value in the env variable THEANO_FLAGS override the previous value
import pdb;pdb.set_trace()
val = default_value
for flag in flags.split(','):
if not flag:
continue
sp=flag.split('=',1)
if sp[0]==name:
if len(sp)==1:
val=True
else:
val=sp[1]
val=str(val)
return val
floatX=parse_env_flags(THEANO_FLAGS,'floatX','float64')
class TheanoConfig(object): class TheanoConfig(object):
"""Return the value for a key after parsing ~/.theano.cfg and """Return the value for a key after parsing ~/.theano.cfg and
the THEANO_FLAGS environment variable. the THEANO_FLAGS environment variable.
...@@ -149,5 +166,6 @@ class TheanoConfig(object): ...@@ -149,5 +166,6 @@ class TheanoConfig(object):
config = TheanoConfig() config = TheanoConfig()
if config.get('scalar.floatX') not in ['float32', 'float64']: if floatX not in ['float32', 'float64']:
raise Exception("the configuration scalar.floatX must have value float32 or float64") raise Exception("the configuration scalar.floatX must have value float32 or float64 not", floatX)
import theano.config as config
from theano.scalar import float32, float64
from theano.tensor import fscalar, fvector, fmatrix, frow, fcol, ftensor3, ftensor4, dscalar, dvector, dmatrix, drow, dcol, dtensor3, dtensor4
def set_floatX(dtype = config.floatX):
""" add the xmatrix, xvector, xscalar etc. aliases to theano.tensor
"""
print "set_floatX",dtype
config.floatX = dtype
import pdb;pdb.set_trace()
if dtype == 'float32': prefix = 'f'
elif dtype == 'float64' : prefix = 'd'
else: raise Exception("Bad param in set_floatX(%s). Only float32 and float64 are supported"%config.floatX)
#tensor.scalar stuff
globals()['floatX'] = globals()[dtype]
# convert_to_floatX = Cast(floatX, name='convert_to_floatX')
#tensor.tensor stuff
for symbol in ('scalar', 'vector', 'matrix', 'row', 'col','tensor3','tensor4'):
globals()['x'+symbol] = globals()[prefix+symbol]
#_convert_to_floatX = _conversion(elemwise.Elemwise(scal.convert_to_floatX), 'floatX')
...@@ -56,8 +56,8 @@ def constant(x): ...@@ -56,8 +56,8 @@ def constant(x):
class Scalar(Type): class Scalar(Type):
def __init__(self, dtype): def __init__(self, dtype):
if dtype=='floatX': if dtype == 'floatX':
dtype=config.config.get('floatX') dtype = config.floatX
self.dtype = dtype self.dtype = dtype
self.dtype_specs() # error checking self.dtype_specs() # error checking
...@@ -261,7 +261,6 @@ uint32 = Scalar('uint32') ...@@ -261,7 +261,6 @@ uint32 = Scalar('uint32')
uint64 = Scalar('uint64') uint64 = Scalar('uint64')
float32 = Scalar('float32') float32 = Scalar('float32')
float64 = Scalar('float64') float64 = Scalar('float64')
floatX = Scalar(config.config.get('scalar.floatX'))
complex64 = Scalar('complex64') complex64 = Scalar('complex64')
complex128 = Scalar('complex128') complex128 = Scalar('complex128')
...@@ -944,7 +943,6 @@ convert_to_uint32 = Cast(uint32, name='convert_to_uint32') ...@@ -944,7 +943,6 @@ convert_to_uint32 = Cast(uint32, name='convert_to_uint32')
convert_to_uint64 = Cast(uint64, name='convert_to_uint64') convert_to_uint64 = Cast(uint64, name='convert_to_uint64')
convert_to_float32 = Cast(float32, name='convert_to_float32') convert_to_float32 = Cast(float32, name='convert_to_float32')
convert_to_float64 = Cast(float64, name='convert_to_float64') convert_to_float64 = Cast(float64, name='convert_to_float64')
convert_to_floatX = Cast(floatX, name='convert_to_floatX')
convert_to_complex64 = Cast(complex64, name='convert_to_complex64') convert_to_complex64 = Cast(complex64, name='convert_to_complex64')
convert_to_complex128 = Cast(complex128, name='convert_to_complex128') convert_to_complex128 = Cast(complex128, name='convert_to_complex128')
...@@ -959,12 +957,11 @@ _cast_mapping = { ...@@ -959,12 +957,11 @@ _cast_mapping = {
'uint64': convert_to_uint64, 'uint64': convert_to_uint64,
'float32': convert_to_float32, 'float32': convert_to_float32,
'float64': convert_to_float64, 'float64': convert_to_float64,
'floatX': convert_to_floatX,
'complex64': convert_to_complex64, 'complex64': convert_to_complex64,
'complex128': convert_to_complex128} 'complex128': convert_to_complex128}
def cast(x, dtype): def cast(x, dtype):
"""Symbolically cast `x` to a Scalar of given `dtype`.""" """Symbolically cast `x` to a Scalar of given `dtype`."""
if dtype=='floatX': dtype = config.config.get('scalar.floatX') if dtype == 'floatX': dtype = config.floatX
_x = as_scalar(x) _x = as_scalar(x)
if _x.type.dtype == dtype: if _x.type.dtype == dtype:
......
...@@ -283,7 +283,7 @@ class TensorType(Type): ...@@ -283,7 +283,7 @@ class TensorType(Type):
""" """
self.dtype = str(dtype) self.dtype = str(dtype)
if self.dtype=='floatX': if self.dtype=='floatX':
self.dtype=config.config.get('scalar.floatX') self.dtype=config.floatX
self.broadcastable = tuple(broadcastable) self.broadcastable = tuple(broadcastable)
self.dtype_specs() # error checking is done there self.dtype_specs() # error checking is done there
self.name = name self.name = name
...@@ -610,7 +610,6 @@ cscalar = TensorType('complex64', ()) ...@@ -610,7 +610,6 @@ cscalar = TensorType('complex64', ())
zscalar = TensorType('complex128', ()) zscalar = TensorType('complex128', ())
fscalar = TensorType('float32', ()) fscalar = TensorType('float32', ())
dscalar = TensorType('float64', ()) dscalar = TensorType('float64', ())
xscalar = TensorType('floatX',())
bscalar = TensorType('int8', ()) bscalar = TensorType('int8', ())
wscalar = TensorType('int16', ()) wscalar = TensorType('int16', ())
iscalar = TensorType('int32', ()) iscalar = TensorType('int32', ())
...@@ -631,7 +630,6 @@ cvector = TensorType('complex64', (False, )) ...@@ -631,7 +630,6 @@ cvector = TensorType('complex64', (False, ))
zvector = TensorType('complex128', (False, )) zvector = TensorType('complex128', (False, ))
fvector = TensorType('float32', (False, )) fvector = TensorType('float32', (False, ))
dvector = TensorType('float64', (False, )) dvector = TensorType('float64', (False, ))
xvector = TensorType('floatX', (False, ))
bvector = TensorType('int8', (False,)) bvector = TensorType('int8', (False,))
wvector = TensorType('int16', (False,)) wvector = TensorType('int16', (False,))
ivector = TensorType('int32', (False, )) ivector = TensorType('int32', (False, ))
...@@ -649,7 +647,6 @@ cmatrix = TensorType('complex64', (False, False)) ...@@ -649,7 +647,6 @@ cmatrix = TensorType('complex64', (False, False))
zmatrix = TensorType('complex128', (False, False)) zmatrix = TensorType('complex128', (False, False))
fmatrix = TensorType('float32', (False, False)) fmatrix = TensorType('float32', (False, False))
dmatrix = TensorType('float64', (False, False)) dmatrix = TensorType('float64', (False, False))
xmatrix = TensorType('floatX', (False, False))
bmatrix = TensorType('int8', (False, False)) bmatrix = TensorType('int8', (False, False))
wmatrix = TensorType('int16', (False, False)) wmatrix = TensorType('int16', (False, False))
imatrix = TensorType('int32', (False, False)) imatrix = TensorType('int32', (False, False))
...@@ -667,7 +664,6 @@ crow = TensorType('complex64', (True, False)) ...@@ -667,7 +664,6 @@ crow = TensorType('complex64', (True, False))
zrow = TensorType('complex128', (True, False)) zrow = TensorType('complex128', (True, False))
frow = TensorType('float32', (True, False)) frow = TensorType('float32', (True, False))
drow = TensorType('float64', (True, False)) drow = TensorType('float64', (True, False))
xrow = TensorType('floatX', (True, False))
brow = TensorType('int8', (True, False)) brow = TensorType('int8', (True, False))
wrow = TensorType('int16', (True, False)) wrow = TensorType('int16', (True, False))
irow = TensorType('int32', (True, False)) irow = TensorType('int32', (True, False))
...@@ -681,7 +677,6 @@ ccol = TensorType('complex64', (False, True)) ...@@ -681,7 +677,6 @@ ccol = TensorType('complex64', (False, True))
zcol = TensorType('complex128', (False, True)) zcol = TensorType('complex128', (False, True))
fcol = TensorType('float32', (False, True)) fcol = TensorType('float32', (False, True))
dcol = TensorType('float64', (False, True)) dcol = TensorType('float64', (False, True))
xcol = TensorType('floatX', (False, True))
bcol = TensorType('int8', (False, True)) bcol = TensorType('int8', (False, True))
wcol = TensorType('int16', (False, True)) wcol = TensorType('int16', (False, True))
icol = TensorType('int32', (False, True)) icol = TensorType('int32', (False, True))
...@@ -695,7 +690,6 @@ ctensor3 = TensorType('complex64', (False,)*3) ...@@ -695,7 +690,6 @@ ctensor3 = TensorType('complex64', (False,)*3)
ztensor3 = TensorType('complex128', (False,)*3) ztensor3 = TensorType('complex128', (False,)*3)
ftensor3 = TensorType('float32', (False,)*3) ftensor3 = TensorType('float32', (False,)*3)
dtensor3 = TensorType('float64', (False,)*3) dtensor3 = TensorType('float64', (False,)*3)
xtensor3 = TensorType('floatX', (False,)*3)
btensor3 = TensorType('int8', (False,)*3) btensor3 = TensorType('int8', (False,)*3)
wtensor3 = TensorType('int16', (False,)*3) wtensor3 = TensorType('int16', (False,)*3)
itensor3 = TensorType('int32', (False,)*3) itensor3 = TensorType('int32', (False,)*3)
...@@ -705,7 +699,6 @@ ctensor4 = TensorType('complex64', (False,)*4) ...@@ -705,7 +699,6 @@ ctensor4 = TensorType('complex64', (False,)*4)
ztensor4 = TensorType('complex128', (False,)*4) ztensor4 = TensorType('complex128', (False,)*4)
ftensor4 = TensorType('float32', (False,)*4) ftensor4 = TensorType('float32', (False,)*4)
dtensor4 = TensorType('float64', (False,)*4) dtensor4 = TensorType('float64', (False,)*4)
xtensor4 = TensorType('floatX', (False,)*4)
btensor4 = TensorType('int8', (False,)*4) btensor4 = TensorType('int8', (False,)*4)
wtensor4 = TensorType('int16', (False,)*4) wtensor4 = TensorType('int16', (False,)*4)
itensor4 = TensorType('int32', (False,)*4) itensor4 = TensorType('int32', (False,)*4)
...@@ -1102,9 +1095,6 @@ _convert_to_float32 = _conversion(elemwise.Elemwise(scal.convert_to_float32), 'f ...@@ -1102,9 +1095,6 @@ _convert_to_float32 = _conversion(elemwise.Elemwise(scal.convert_to_float32), 'f
_convert_to_float64 = _conversion(elemwise.Elemwise(scal.convert_to_float64), 'float64') _convert_to_float64 = _conversion(elemwise.Elemwise(scal.convert_to_float64), 'float64')
"""Cast to double-precision floating point""" """Cast to double-precision floating point"""
_convert_to_floatX = _conversion(elemwise.Elemwise(scal.convert_to_floatX), 'floatX')
"""Cast to floatX floating point"""
_convert_to_complex64 = _conversion(elemwise.Elemwise(scal.convert_to_complex64), 'complex64') _convert_to_complex64 = _conversion(elemwise.Elemwise(scal.convert_to_complex64), 'complex64')
"""Cast to single-precision complex""" """Cast to single-precision complex"""
...@@ -1122,13 +1112,12 @@ _cast_mapping = { ...@@ -1122,13 +1112,12 @@ _cast_mapping = {
'uint64': _convert_to_uint64, 'uint64': _convert_to_uint64,
'float32': _convert_to_float32, 'float32': _convert_to_float32,
'float64': _convert_to_float64, 'float64': _convert_to_float64,
'floatX': _convert_to_floatX,
'complex64': _convert_to_complex64, 'complex64': _convert_to_complex64,
'complex128': _convert_to_complex128} 'complex128': _convert_to_complex128}
@constructor @constructor
def cast(x, dtype): def cast(x, dtype):
"""Symbolically cast `x` to a Tensor of type `dtype`.""" """Symbolically cast `x` to a Tensor of type `dtype`."""
if dtype=='floatX': dtype = config.config.get('scalar.floatX') if dtype=='floatX': dtype = config.floatX
_x = as_tensor_variable(x) _x = as_tensor_variable(x)
if _x.type.dtype == dtype: if _x.type.dtype == dtype:
......
...@@ -2218,63 +2218,6 @@ def test_default_state(): ...@@ -2218,63 +2218,6 @@ def test_default_state():
assert f(1) == 4.8 assert f(1) == 4.8
assert f(2.2) == 7 assert f(2.2) == 7
def test_cast_floatX():
floatx=config.config.get('scalar.floatX')
#float64 cast to float64 should not generate an op
x = dvector('x')
f = function([x],[cast(x,'float64')])
# print f.maker.env.toposort()
assert len(f.maker.env.toposort())==0
#float32 cast to float32 should not generate an op
x = fvector('x')
f = function([x],[cast(x,'float32')])
# print f.maker.env.toposort()
assert len(f.maker.env.toposort())==0
#floatX cast to float64
x = xvector('x')
f = function([x],[cast(x,'float64')])
# print f.maker.env.toposort()
if floatx=='float64':
assert len(f.maker.env.toposort()) == 0
else:
assert len(f.maker.env.toposort()) == 1
#floatX cast to float32
x = xvector('x')
f = function([x],[cast(x,'float32')])
# print f.maker.env.toposort()
if floatx=='float32':
assert len(f.maker.env.toposort()) == 0
else:
assert len(f.maker.env.toposort()) == 1
#float64 cast to floatX
x = dvector('x')
f = function([x],[cast(x,'floatX')])
# print f.maker.env.toposort()
if floatx=='float64':
assert len(f.maker.env.toposort()) == 0
else:
assert len(f.maker.env.toposort()) == 1
#float32 cast to floatX
x = fvector('x')
f = function([x],[cast(x,'floatX')])
# print f.maker.env.toposort()
if floatx=='float32':
assert len(f.maker.env.toposort()) == 0
else:
assert len(f.maker.env.toposort()) == 1
#floatX cast to floatX
x = xvector('x')
f = function([x],[cast(x,'floatX')])
# print f.maker.env.toposort()
assert len(f.maker.env.toposort()) == 0
if __name__ == '__main__': if __name__ == '__main__':
if len(sys.argv) >= 2 and sys.argv[1] == 'OPT': if len(sys.argv) >= 2 and sys.argv[1] == 'OPT':
default_mode = compile.Mode(linker = 'c&py', default_mode = compile.Mode(linker = 'c&py',
......
from theano.tensor import *
import theano.config as config
from theano import function
#from theano.floatx import set_floatX, xscalar, xmatrix, xrow, xcol, xvector, xtensor3, xtensor4
import theano.floatx as FX
def test_floatX():
def test():
floatx=config.floatX
#TODO test other fct then ?vector
#float64 cast to float64 should not generate an op
x = dvector('x')
f = function([x],[cast(x,'float64')])
# print f.maker.env.toposort()
assert len(f.maker.env.toposort())==0
#float32 cast to float32 should not generate an op
x = fvector('x')
f = function([x],[cast(x,'float32')])
# print f.maker.env.toposort()
assert len(f.maker.env.toposort())==0
#floatX cast to float64
x = FX.xvector('x')
f = function([x],[cast(x,'float64')])
# print f.maker.env.toposort()
if floatx=='float64':
assert len(f.maker.env.toposort()) == 0
else:
assert len(f.maker.env.toposort()) == 1
#floatX cast to float32
x = FX.xvector('x')
f = function([x],[cast(x,'float32')])
# print f.maker.env.toposort()
if floatx=='float32':
assert len(f.maker.env.toposort()) == 0
else:
assert len(f.maker.env.toposort()) == 1
#float64 cast to floatX
x = dvector('x')
f = function([x],[cast(x,'floatX')])
# print f.maker.env.toposort()
if floatx=='float64':
assert len(f.maker.env.toposort()) == 0
else:
assert len(f.maker.env.toposort()) == 1
#float32 cast to floatX
x = fvector('x')
f = function([x],[cast(x,'floatX')])
# print f.maker.env.toposort()
if floatx=='float32':
assert len(f.maker.env.toposort()) == 0
else:
assert len(f.maker.env.toposort()) == 1
#floatX cast to floatX
x = FX.xvector('x')
f = function([x],[cast(x,'floatX')])
# print f.maker.env.toposort()
assert len(f.maker.env.toposort()) == 0
orig_floatx = config.floatX
try:
print 'float32'
FX.set_floatX('float32')
test()
print 'float64'
FX.set_floatX('float64')
test()
finally:
pass
FX.set_floatX(orig_floatx)
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论