Conditions
IfElse vs Switch
- Both ops build a condition over symbolic variables.
IfElse
takes a boolean condition and two variables as inputs.Switch
takes a tensor as condition and two variables as inputs.switch
is an elementwise operation and is thus more general thanifelse
.- Whereas
switch
evaluates both output variables,ifelse
is lazy and onlyevaluates one variable with respect to the condition.
Example
- from theano import tensor as T
- from theano.ifelse import ifelse
- import theano, time, numpy
- a,b = T.scalars('a', 'b')
- x,y = T.matrices('x', 'y')
- z_switch = T.switch(T.lt(a, b), T.mean(x), T.mean(y))
- z_lazy = ifelse(T.lt(a, b), T.mean(x), T.mean(y))
- f_switch = theano.function([a, b, x, y], z_switch,
- mode=theano.Mode(linker='vm'))
- f_lazyifelse = theano.function([a, b, x, y], z_lazy,
- mode=theano.Mode(linker='vm'))
- val1 = 0.
- val2 = 1.
- big_mat1 = numpy.ones((10000, 1000))
- big_mat2 = numpy.ones((10000, 1000))
- n_times = 10
- tic = time.clock()
- for i in range(n_times):
- f_switch(val1, val2, big_mat1, big_mat2)
- print('time spent evaluating both values %f sec' % (time.clock() - tic))
- tic = time.clock()
- for i in range(n_times):
- f_lazyifelse(val1, val2, big_mat1, big_mat2)
- print('time spent evaluating one value %f sec' % (time.clock() - tic))
In this example, the IfElse
op spends less time (about half as much) than Switch
since it computes only one variable out of the two.
- $ python ifelse_switch.py
- time spent evaluating both values 0.6700 sec
- time spent evaluating one value 0.3500 sec
Unless linker='vm'
or linker='cvm'
are used, ifelse
will compute bothvariables and take the same computation time as switch
. Although the linkeris not currently set by default to cvm
, it will be in the near future.
There is no automatic optimization replacing a switch
with abroadcasted scalar to an ifelse
, as this is not always faster. Seethis ticket.
Note
If you use test values, then all branches ofthe IfElse will be computed. This is normal, as using test_valuemeans everything will be computed when we build it, due to Python’sgreedy evaluation and the semantic of test value. As we build bothbranches, they will be executed for test values. This doesn’t causeany changes during the execution of the compiled Theano function.