Ejemplo n.º 1
0
 def test_src_data_region(self):
     ''' Accessor src_data_region. '''
     nr1 = NodeRegion(dim=PhyDim2(2, 1),
                      origin=PhyDim2(0, 0),
                      type=NodeRegion.DATA)
     nr2 = NodeRegion(dim=PhyDim2(2, 1),
                      origin=PhyDim2(0, 1),
                      type=NodeRegion.DATA)
     resource = Resource(proc_region=NodeRegion(dim=PhyDim2(4, 4),
                                                origin=PhyDim2(0, 0),
                                                type=NodeRegion.PROC),
                         dim_array=PhyDim2(16, 16),
                         size_gbuf=131072,
                         size_regf=512,
                         data_regions=(nr1, nr2))
     self.assertEqual(resource.src_data_region(), nr1, 'src_data_region')
     resource = Resource(proc_region=NodeRegion(dim=PhyDim2(4, 4),
                                                origin=PhyDim2(0, 0),
                                                type=NodeRegion.PROC),
                         dim_array=PhyDim2(16, 16),
                         size_gbuf=131072,
                         size_regf=512,
                         data_regions=(nr1, ))
     self.assertEqual(resource.src_data_region(), nr1, 'src_data_region')
Ejemplo n.º 2
0
class TestScheduling(unittest.TestCase):
    ''' Tests for Scheduling module. '''

    def setUp(self):

        self.layers = {}
        self.layers['BASE'] = ConvLayer(8, 16, 28, 3)
        self.layers['POOL'] = PoolingLayer(16, 28, 2)
        self.layers['LR'] = LocalRegionLayer(16, 28, nreg=3, sreg=1)

        self.batch_size = 4

        self.cost = Cost(mac_op=1, mem_hier=(200, 6, 2, 1),
                         noc_hop=50, unit_static=50)

        self.resource = Resource(
            proc_region=NodeRegion(origin=PhyDim2(0, 0), dim=PhyDim2(4, 4),
                                   type=NodeRegion.PROC),
            data_regions=(NodeRegion(origin=PhyDim2(0, 0), dim=PhyDim2(4, 1),
                                     type=NodeRegion.DATA),),
            dim_array=PhyDim2(16, 16), size_gbuf=65536, size_regf=64)

        self.options = Option(partition_hybrid=True, partition_batch=True,
                              partition_ifmaps=True, ntops=10)

        self.ifmap_layouts = {}
        part = PartitionScheme(order=(pe.INPP, pe.BATP, pe.OUTP, pe.OFMP),
                               pdims=((1, 2), (2, 1), (1, 2), (2, 1)))
        for wlkey in self.layers:
            self.ifmap_layouts[wlkey] = partition.get_ofmap_layout(
                self.layers[wlkey].input_layer(), self.batch_size, part,
                self.resource.src_data_region())

    def test_valid_args(self):
        ''' Valid arguments for constructor. '''
        schd = Scheduling(self.layers['BASE'], self.batch_size, self.cost,
                          MapStrategyEyeriss)

        self.assertEqual(schd.layer, self.layers['BASE'])
        self.assertEqual(schd.batch_size, self.batch_size)
        self.assertEqual(schd.cost, self.cost)
        self.assertEqual(schd.map_strategy_class, MapStrategyEyeriss)

    def test_invalid_layer(self):
        ''' Invalid layer argument. '''
        with self.assertRaisesRegexp(TypeError, 'Scheduling: .*layer.*'):
            _ = Scheduling((64, 128, 28, 3), self.batch_size, self.cost,
                           MapStrategyEyeriss)

    def test_invalid_cost(self):
        ''' Invalid cost argument. '''
        with self.assertRaisesRegexp(TypeError, 'Scheduling: .*cost.*'):
            _ = Scheduling(self.layers['BASE'], self.batch_size,
                           tuple(self.cost), MapStrategyEyeriss)

    def test_invalid_map_strategy(self):
        ''' Invalid cost argument. '''
        class _DummyClass(object):  # pylint: disable=too-few-public-methods
            pass

        with self.assertRaisesRegexp(TypeError,
                                     'Scheduling: .*map_strategy_class.*'):
            _ = Scheduling(self.layers['BASE'], self.batch_size, self.cost,
                           _DummyClass)

    def test_schedule_search(self):
        ''' Schedule search. '''
        for wlkey in self.layers:
            layer = self.layers[wlkey]
            ifmap_layout = self.ifmap_layouts[wlkey]

            schd = Scheduling(layer, self.batch_size, self.cost,
                              MapStrategyEyeriss)

            condition = SchedulingCondition(resource=self.resource,
                                            ifmap_layout=ifmap_layout)

            res = schd.schedule_search(condition, self.options)

            # Top N.
            self.assertLessEqual(len(res), self.options.ntops)
            self.assertTrue(all(isinstance(r, SchedulingResult) for r in res))
            for idx in range(len(res) - 1):
                self.assertLessEqual(res[idx].total_cost,
                                     res[idx + 1].total_cost)

            # Combination of loop blocking and partitioning.
            for r in res:
                self.assertEqual(r.total_cost,
                                 r.dict_loop['cost'] + r.dict_part['cost'])
                self.assertEqual(r.dict_loop['ops'],
                                 layer.total_ops(self.batch_size))
                self.assertSequenceEqual(r.dict_part['total_nhops'],
                                         [nh * f for nh, f
                                          in zip(r.dict_part['unit_nhops'],
                                                 r.dict_loop['fetch'][0])])
                self.assertEqual(r.dict_part['num_nodes'],
                                 self.resource.proc_region.dim.size())

            # Ofmap layout.
            for r in res:
                self.assertEqual(r.ofmap_layout.frmap.complete_fmap_range()
                                 .size(),
                                 layer.total_ofmap_size(self.batch_size))

    def test_schedule_search_ilayout(self):
        ''' Invalid ifmap_layout. '''
        layer = self.layers['BASE']
        ifmap_layout = self.ifmap_layouts['BASE']

        schd = Scheduling(layer, self.batch_size, self.cost,
                          MapStrategyEyeriss)

        # Shift ifmap out of memory region.
        condition = SchedulingCondition(
            resource=self.resource,
            ifmap_layout=ifmap_layout.view(PhyDim2(1, 1)))

        with self.assertRaisesRegexp(ValueError, 'Scheduling: .*ifmap.*'):
            _ = schd.schedule_search(condition, self.options)

        # Not match layer.
        condition = SchedulingCondition(
            resource=self.resource,
            ifmap_layout=self.ifmap_layouts['POOL'])

        with self.assertRaisesRegexp(ValueError, 'Scheduling: .*ifmap.*'):
            _ = schd.schedule_search(condition, self.options)

    def test_pernode_sched_cache(self):
        ''' Per-node scheduling cache. '''
        layer = self.layers['BASE']
        ifmap_layout = self.ifmap_layouts['BASE']

        schd = Scheduling(layer, self.batch_size, self.cost,
                          MapStrategyEyeriss)

        self.assertEqual(len(schd.pernode_sched_cache), 0)
        self.assertTupleEqual(schd.cache_stats(), (0, 0))

        condition = SchedulingCondition(resource=self.resource,
                                        ifmap_layout=ifmap_layout)

        _ = schd.schedule_search(condition, self.options)

        h, m = schd.cache_stats()
        self.assertEqual(len(schd.pernode_sched_cache), m)
        self.assertEqual(h, 0)
        n = m

        _ = schd.schedule_search(condition, self.options)

        self.assertEqual(len(schd.pernode_sched_cache), n)
        self.assertTupleEqual(schd.cache_stats(), (n, n))

    def test_pernode_sched_cache_key(self):
        ''' Per-node scheduling cache key must be hash-able. '''
        layer = self.layers['BASE']
        ifmap_layout = self.ifmap_layouts['BASE']

        schd = Scheduling(layer, self.batch_size, self.cost,
                          MapStrategyEyeriss)

        condition = SchedulingCondition(resource=self.resource,
                                        ifmap_layout=ifmap_layout)

        _ = schd.schedule_search(condition, self.options)

        h, m = schd.cache_stats()
        self.assertEqual(h, 0)

        # Make another instance.
        rsrc = Resource(**self.resource._asdict())
        opts = Option(**self.options._asdict())
        self.assertNotEqual(id(rsrc), id(self.resource))
        self.assertNotEqual(id(opts), id(self.options))

        part = PartitionScheme(order=(pe.BATP, pe.INPP, pe.OUTP, pe.OFMP),
                               pdims=((2, 2), (2, 2), (1, 1), (1, 1)))

        _ = schd.schedule_search_per_node(part, rsrc, opts)

        h2, m2 = schd.cache_stats()
        self.assertEqual(h2, h + 1)
        self.assertEqual(m2, m)