op_test_util.py 2.5 KB
Newer Older
Y
Yu Yang 已提交
1 2 3
import paddle.v2.framework.core as core
import unittest
import numpy
Y
Yu Yang 已提交
4
from paddle.v2.framework.op import Operator
Y
Yu Yang 已提交
5 6 7


class OpTestMeta(type):
Y
Yu Yang 已提交
8 9 10 11 12 13 14 15 16 17 18 19
    """
    Operator Test ClassMeta.
    
    It injects `test_all` method into user's OperatorTest class, to make Python 
    unittest module run that method.
    
    The `test_all` read what value is stored in `self`. It use self's values to
    create and run a operator, and check whether that op is OK or not.
    
    See `test_add_two_op` for example usage.
    """

Y
Yu Yang 已提交
20 21 22 23
    def __new__(cls, name, bases, attrs):
        obj = super(OpTestMeta, cls).__new__(cls, name, bases, attrs)

        def test_all(self):
Y
Yu Yang 已提交
24
            scope = core.Scope()
Y
Yu Yang 已提交
25
            kwargs = dict()
Y
Yu Yang 已提交
26
            places = [core.CPUPlace()]
Q
qijun 已提交
27 28 29 30
            if core.is_compile_gpu():
                places.append(core.GPUPlace(0))

            for place in places:
Y
Yu Yang 已提交
31
                for in_name in Operator.get_op_input_names(self.type):
Q
qijun 已提交
32 33
                    if hasattr(self, in_name):
                        kwargs[in_name] = in_name
Q
qijun 已提交
34
                        var = scope.new_var(in_name).get_tensor()
Q
qijun 已提交
35 36 37 38 39
                        arr = getattr(self, in_name)
                        var.set_dims(arr.shape)
                        var.set(arr, place)
                    else:
                        kwargs[in_name] = "@EMPTY@"
Y
Yu Yang 已提交
40

Y
Yu Yang 已提交
41
                for out_name in Operator.get_op_output_names(self.type):
Q
qijun 已提交
42 43
                    if hasattr(self, out_name):
                        kwargs[out_name] = out_name
Q
qijun 已提交
44
                        scope.new_var(out_name).get_tensor()
Y
Yu Yang 已提交
45

Y
Yu Yang 已提交
46
                for attr_name in Operator.get_op_attr_names(self.type):
Q
qijun 已提交
47 48
                    if hasattr(self, attr_name):
                        kwargs[attr_name] = getattr(self, attr_name)
Y
Yu Yang 已提交
49

Y
Yu Yang 已提交
50
                op = Operator(self.type, **kwargs)
Y
Yu Yang 已提交
51

Q
qijun 已提交
52
                op.infer_shape(scope)
Y
Yu Yang 已提交
53

Q
qijun 已提交
54 55
                ctx = core.DeviceContext.create(place)
                op.run(scope, ctx)
Y
Yu Yang 已提交
56

Y
Yu Yang 已提交
57
                for out_name in Operator.get_op_output_names(self.type):
Q
qijun 已提交
58
                    actual = numpy.array(scope.find_var(out_name).get_tensor())
Q
qijun 已提交
59 60 61 62 63
                    expect = getattr(self, out_name)
                    # TODO(qijun) The default decimal is 7, but numpy.dot and eigen.mul
                    # has some diff, and could not pass unittest. So I set decimal 3 here.
                    # And I will check this in future.
                    numpy.testing.assert_almost_equal(actual, expect, decimal=3)
Y
Yu Yang 已提交
64 65 66

        obj.test_all = test_all
        return obj