def test_invalid_unit_access_len(self): ''' Invalid unit_access len. ''' with self.assertRaisesRegexp(ValueError, 'NestedLoopDesc: .*unit_access.*'): _ = NestedLoopDesc(loopcnt=(3, 8, 4), usize_gbuf=(20, 30, 9), usize_regf=(3, 3, 1), unit_access=((19, 29, 9), (35, 45, 15), (1, 1, 2)), data_loops=(DataDimLoops(le.IFM, le.OFM), DataDimLoops(le.IFM, le.BAT), DataDimLoops(le.OFM, le.BAT)), unit_ops=7, unit_time=7) with self.assertRaisesRegexp(ValueError, 'NestedLoopDesc: .*unit_access.*'): _ = NestedLoopDesc(loopcnt=(3, 8, 4), usize_gbuf=(20, 30, 9), usize_regf=(3, 3, 1), unit_access=((19, 29, 9), (18, 28), (35, 45, 15), (1, 1, 2)), data_loops=(DataDimLoops(le.IFM, le.OFM), DataDimLoops(le.IFM, le.BAT), DataDimLoops(le.OFM, le.BAT)), unit_ops=7, unit_time=7)
def test_total_access_of_at(self): ''' Get total_access_of_at. ''' nld = NestedLoopDesc(loopcnt=(3, 8, 4), usize_gbuf=(20, 30, 9), usize_regf=(3, 3, 1), unit_access=((19, 29, 9), (18, 28, 8), (35, 45, 15), (1, 1, 2)), data_loops=(DataDimLoops(le.IFM, le.OFM), DataDimLoops(le.IFM, le.BAT), DataDimLoops(le.OFM, le.BAT)), unit_ops=7, unit_time=7 ) self.assertEqual(nld.total_access_at_of(me.DRAM, de.FIL), 19 * 3 * 8) self.assertEqual(nld.total_access_at_of(me.DRAM, de.IFM), 29 * 3 * 4) self.assertEqual(nld.total_access_at_of(me.DRAM, de.OFM), 9 * 8 * 4) self.assertEqual(nld.total_access_at_of(me.GBUF, de.FIL), 18 * 3 * 8) self.assertEqual(nld.total_access_at_of(me.GBUF, de.IFM), 28 * 3 * 4) self.assertEqual(nld.total_access_at_of(me.GBUF, de.OFM), 8 * 8 * 4) self.assertEqual(nld.total_access_at_of(me.ITCN, de.FIL), 35 * 3 * 8) self.assertEqual(nld.total_access_at_of(me.ITCN, de.IFM), 45 * 3 * 4) self.assertEqual(nld.total_access_at_of(me.ITCN, de.OFM), 15 * 8 * 4) self.assertEqual(nld.total_access_at_of(me.REGF, de.FIL), 1 * 3 * 8) self.assertEqual(nld.total_access_at_of(me.REGF, de.IFM), 1 * 3 * 4) self.assertEqual(nld.total_access_at_of(me.REGF, de.OFM), 2 * 8 * 4)
def test_invalid_data_loops_type(self): ''' Invalid data_loops type. ''' with self.assertRaisesRegex(TypeError, 'NestedLoopDesc: .*data_loops.*'): _ = NestedLoopDesc(loopcnt=(3, 8, 4), usize_gbuf=(20, 30, 9), usize_regf=(3, 3, 1), unit_access=((19, 29, 9), (18, 28, 8), (35, 45, 15), (1, 1, 2)), data_loops=[DataDimLoops(le.IFM, le.OFM), DataDimLoops(le.IFM, le.BAT), DataDimLoops(le.OFM, le.BAT)], unit_ops=7, unit_time=7 ) with self.assertRaisesRegex(TypeError, 'NestedLoopDesc: .*data_loops.*'): _ = NestedLoopDesc(loopcnt=(3, 8, 4), usize_gbuf=(20, 30, 9), usize_regf=(3, 3, 1), unit_access=((19, 29, 9), (18, 28, 8), (35, 45, 15), (1, 1, 2)), data_loops=((le.IFM, le.OFM), (le.IFM, le.BAT), (le.OFM, le.BAT)), unit_ops=7, unit_time=7 )
def test_total_ops(self): ''' Get total_ops. ''' nld = NestedLoopDesc(loopcnt=(3, 8, 4), usize_gbuf=(20, 30, 9), usize_regf=(3, 3, 1), unit_access=((19, 29, 9), (18, 28, 8), (35, 45, 15), (1, 1, 2)), data_loops=(DataDimLoops(le.IFM, le.OFM), DataDimLoops(le.IFM, le.BAT), DataDimLoops(le.OFM, le.BAT)), unit_ops=7, unit_time=7) self.assertEqual(nld.total_ops(), 7 * 3 * 8 * 4)
def test_usize_regf_of(self): ''' Accessor usize_regf. ''' nld = NestedLoopDesc(loopcnt=(3, 8, 4), usize_gbuf=(20, 30, 9), usize_regf=(3, 3, 1), unit_access=((19, 29, 9), (18, 28, 8), (35, 45, 15), (1, 1, 2)), data_loops=(DataDimLoops(le.IFM, le.OFM), DataDimLoops(le.IFM, le.BAT), DataDimLoops(le.OFM, le.BAT)), unit_ops=7, unit_time=7) self.assertEqual(nld.usize_regf_of(de.FIL), 3, 'usize_regf: FIL') self.assertEqual(nld.usize_regf_of(de.IFM), 3, 'usize_regf: IFM') self.assertEqual(nld.usize_regf_of(de.OFM), 1, 'usize_regf: OFM')
def test_valid_args(self): ''' Valid arguments. ''' nld = NestedLoopDesc(loopcnt=(3, 8, 4), usize_gbuf=(20, 30, 9), usize_regf=(3, 3, 1), unit_access=((19, 29, 9), (18, 28, 8), (35, 45, 15), (1, 1, 2)), data_loops=(DataDimLoops(le.IFM, le.OFM), DataDimLoops(le.IFM, le.BAT), DataDimLoops(le.OFM, le.BAT)), unit_ops=7, unit_time=7 ) self.assertEqual(nld.loopcnt, (3, 8, 4), 'loopcnt') self.assertEqual(nld.usize_gbuf, (20, 30, 9), 'usize_gbuf') self.assertEqual(nld.usize_regf, (3, 3, 1), 'usize_regf') self.assertEqual(nld.unit_access, ((19, 29, 9), (18, 28, 8), (35, 45, 15), (1, 1, 2)), 'unit_access') self.assertEqual(nld.data_loops[de.FIL], DataDimLoops(le.IFM, le.OFM), 'data_loops: FIL') self.assertEqual(nld.data_loops[de.IFM], DataDimLoops(le.IFM, le.BAT), 'data_loops: IFM') self.assertEqual(nld.data_loops[de.OFM], DataDimLoops(le.OFM, le.BAT), 'data_loops: OFM') self.assertEqual(nld.unit_ops, 7, 'unit_ops') self.assertEqual(nld.unit_time, 7, 'unit_time')
def test_unit_access_at_of(self): ''' Accessor unit_access. ''' nld = NestedLoopDesc(loopcnt=(3, 8, 4), usize_gbuf=(20, 30, 9), usize_regf=(3, 3, 1), unit_access=((19, 29, 9), (18, 28, 8), (35, 45, 15), (1, 1, 2)), data_loops=(DataDimLoops(le.IFM, le.OFM), DataDimLoops(le.IFM, le.BAT), DataDimLoops(le.OFM, le.BAT)), unit_ops=7, unit_time=7) self.assertEqual(nld.unit_access_at_of(me.DRAM), 19 + 29 + 9, 'unit_access: DRAM') self.assertEqual(nld.unit_access_at_of(me.ITCN), 35 + 45 + 15, 'unit_access: ITCN') self.assertEqual(nld.unit_access_at_of(me.GBUF, de.OFM), 8, 'unit_access: GBUF, OFM') self.assertEqual(nld.unit_access_at_of(me.REGF, de.FIL), 1, 'unit_access: REGF, FIL')
def setUp(self): # Workload. self.layer = {} self.layer['BASE'] = ConvLayer(12, 10, 28, 3) self.layer['LGFIL'] = ConvLayer(2, 4, 28, 20) self.layer['POOL'] = PoolingLayer(32, 28, 2) self.layer['PAR'] = ConvLayer(24, 36, 56, 3) self.batch_size = 4 # Resource. self.resource = {} dim_array = PhyDim2(16, 16) proc_region = NodeRegion(origin=PhyDim2(0, 0), dim=PhyDim2(1, 1), type=NodeRegion.PROC) data_region = NodeRegion(origin=PhyDim2(0, 0), dim=PhyDim2(1, 1), type=NodeRegion.DRAM) # Typical resource. self.resource['BASE'] = Resource(proc_region=proc_region, dram_region=data_region, src_data_region=data_region, dst_data_region=data_region, dim_array=dim_array, size_gbuf=65536, size_regf=64, array_bus_width=float('inf'), dram_bandwidth=float('inf'), no_time_mux=False) # Larger resource with sufficient capacity, to make all schemes valid. self.resource['LG'] = Resource(proc_region=proc_region, dram_region=data_region, src_data_region=data_region, dst_data_region=data_region, dim_array=dim_array, size_gbuf=1024**3, size_regf=1024**3, array_bus_width=float('inf'), dram_bandwidth=float('inf'), no_time_mux=False) # Small resource. self.resource['SM'] = Resource(proc_region=proc_region, dram_region=data_region, src_data_region=data_region, dst_data_region=data_region, dim_array=dim_array, size_gbuf=4096, size_regf=16, array_bus_width=float('inf'), dram_bandwidth=float('inf'), no_time_mux=False) # Multi-node parallel resource. self.resource['PAR'] = Resource(proc_region=NodeRegion( origin=PhyDim2(0, 0), dim=PhyDim2(4, 2), type=NodeRegion.PROC), dram_region=data_region, src_data_region=data_region, dst_data_region=data_region, dim_array=dim_array, size_gbuf=25000, size_regf=64, array_bus_width=float('inf'), dram_bandwidth=float('inf'), no_time_mux=False) # Resource with no data regions. proc_data_region = NodeRegion(origin=PhyDim2(1, 1), dim=PhyDim2(1, 1), type=NodeRegion.PROC) self.resource['SRCNOTDATA'] = Resource( proc_region=proc_region, dram_region=data_region, src_data_region=proc_data_region, dst_data_region=data_region, dim_array=dim_array, size_gbuf=1024**3, size_regf=1024**3, array_bus_width=float('inf'), dram_bandwidth=float('inf'), no_time_mux=False) self.resource['DSTNOTDATA'] = Resource( proc_region=proc_region, dram_region=data_region, src_data_region=data_region, dst_data_region=proc_data_region, dim_array=dim_array, size_gbuf=1024**3, size_regf=1024**3, array_bus_width=float('inf'), dram_bandwidth=float('inf'), no_time_mux=False) self.resource['DATALOCAL'] = Resource(proc_region=proc_region, dram_region=data_region, src_data_region=proc_region, dst_data_region=proc_region, dim_array=dim_array, size_gbuf=1024**3, size_regf=1024**3, array_bus_width=float('inf'), dram_bandwidth=float('inf'), no_time_mux=False) # Filter pinning. self.resource['FILPIN'] = Resource(proc_region=proc_region, dram_region=data_region, src_data_region=data_region, dst_data_region=data_region, dim_array=dim_array, size_gbuf=1024**3, size_regf=1024**3, array_bus_width=float('inf'), dram_bandwidth=float('inf'), no_time_mux=True) # Nested loop description after mapping. self.nld = {} self.nld['BASE'] = next( MapStrategyEyeriss(self.layer['BASE'], self.batch_size, 1, dim_array).gen_nested_loop_desc()) self.nld['LGFIL'] = next( MapStrategyEyeriss(self.layer['LGFIL'], self.batch_size, 1, dim_array).gen_nested_loop_desc()) self.nld['POOL'] = next( MapStrategyEyeriss(self.layer['POOL'], self.batch_size, 1, dim_array).gen_nested_loop_desc()) # Fake nested loop, with zero filter size. self.nld['ZERO_FIL'] = NestedLoopDesc( loopcnt=(12, 10, 4), usize_gbuf=(0, 1000, 800), usize_regf=(0, 3, 1), unit_access=((0, 1000, 800), (0, 1000, 800), (3, 9, 7), (1, 1, 1)), data_loops=(DataDimLoops(le.IFM, le.OFM), DataDimLoops(le.IFM, le.BAT), DataDimLoops(le.OFM, le.BAT)), unit_ops=1, unit_time=1) # Fake nested loop, with zero ifmap size. self.nld['ZERO_IFM'] = NestedLoopDesc( loopcnt=(12, 10, 4), usize_gbuf=(9, 0, 800), usize_regf=(3, 0, 1), unit_access=((9, 0, 800), (9, 0, 800), (3, 9, 7), (1, 1, 1)), data_loops=(DataDimLoops(le.IFM, le.OFM), DataDimLoops(le.IFM, le.BAT), DataDimLoops(le.OFM, le.BAT)), unit_ops=1, unit_time=1) # Fake partition scheme. self.part = PartitionScheme(range(pe.NUM), ((1, 1), ) * pe.NUM) # Fake buffer sharing scheme. self.bufshr = BufShrScheme(proc_region, self.part) # Options. self.options = {} # Basic. self.options['BASE'] = Option(ntops=2**30) # Multiprocessing. self.options['MP'] = Option(ntops=2**30, nprocesses=8) # Limited top schemes. self.options['NTOPS'] = Option(ntops=10) # Bypass. self.options['BYP'] = Option(sw_gbuf_bypass=(True, ) * 3, ntops=2**30) # Bypass solver. self.options['BYPSOL'] = Option(sw_gbuf_bypass=(True, ) * 3, sw_solve_loopblocking=True, ntops=2**30) # Access forwarding. self.options['ACCFWD'] = Option(hw_access_forwarding=True, ntops=2**30) # Buffer sharing. self.options['BUFSHR'] = Option(hw_gbuf_sharing=True, ntops=2**30) # Buffer sharing with bypassing. self.options['BUFSHR-BYP'] = Option(sw_gbuf_bypass=(True, ) * 3, hw_gbuf_sharing=True, ntops=2**30) # Constraint. self.none_cstr = SchedulingConstraint() self.cstr = SchedulingConstraint(topifm=1, topbat=1) # Cost. self.cost = Cost(mac_op=1, mem_hier=(200, 6, 2, 1), noc_hop=50, idl_unit=50)
def setUp(self): # Workload. self.layer = {} self.layer['BASE'] = ConvLayer(12, 10, 28, 3) self.layer['LGFIL'] = ConvLayer(2, 4, 28, 20) self.layer['POOL'] = PoolingLayer(32, 28, 2) self.batch_size = 4 # Resource. self.resource = {} dim_array = PhyDim2(16, 16) proc_region = NodeRegion(origin=PhyDim2(0, 0), dim=PhyDim2(1, 1), type=NodeRegion.PROC) data_regions = (NodeRegion(origin=PhyDim2(0, 0), dim=PhyDim2(1, 1), type=NodeRegion.DATA), ) # Typical resource. self.resource['BASE'] = Resource(proc_region=proc_region, data_regions=data_regions, dim_array=dim_array, size_gbuf=65536, size_regf=64) # Larger resource with sufficient capacity, to make all schemes valid. self.resource['LG'] = Resource(proc_region=proc_region, data_regions=data_regions, dim_array=dim_array, size_gbuf=1024**3, size_regf=1024**3) # Small resource. self.resource['SM'] = Resource(proc_region=proc_region, data_regions=data_regions, dim_array=dim_array, size_gbuf=4096, size_regf=16) # Nested loop description after mapping. self.nld = {} self.nld['BASE'] = next( MapStrategyEyeriss(self.layer['BASE'], self.batch_size, dim_array).gen_nested_loop_desc()) self.nld['LGFIL'] = next( MapStrategyEyeriss(self.layer['LGFIL'], self.batch_size, dim_array).gen_nested_loop_desc()) self.nld['POOL'] = next( MapStrategyEyeriss(self.layer['POOL'], self.batch_size, dim_array).gen_nested_loop_desc()) # Fake nested loop, with zero filter size. self.nld['ZERO_FIL'] = NestedLoopDesc( loopcnt=(12, 10, 4), usize_gbuf=(0, 1000, 800), usize_regf=(0, 3, 1), unit_access=((0, 1000, 800), (0, 1000, 800), (3, 9, 7), (1, 1, 1)), data_loops=(DataDimLoops(le.IFM, le.OFM), DataDimLoops(le.IFM, le.BAT), DataDimLoops(le.OFM, le.BAT)), unit_ops=1, unit_time=1) # Fake nested loop, with zero ifmap size. self.nld['ZERO_IFM'] = NestedLoopDesc( loopcnt=(12, 10, 4), usize_gbuf=(9, 0, 800), usize_regf=(3, 0, 1), unit_access=((9, 0, 800), (9, 0, 800), (3, 9, 7), (1, 1, 1)), data_loops=(DataDimLoops(le.IFM, le.OFM), DataDimLoops(le.IFM, le.BAT), DataDimLoops(le.OFM, le.BAT)), unit_ops=1, unit_time=1) # Options. self.options = {} # Basic. self.options['BASE'] = Option(ntops=2**30) # Multiprocessing. self.options['MP'] = Option(ntops=2**30, nprocesses=8) # Limited top schemes. self.options['NTOPS'] = Option(ntops=10) # Bypass. self.options['BYP'] = Option(sw_gbuf_bypass=(True, ) * 3, ntops=2**30) # Bypass solver. self.options['BYPSOL'] = Option(sw_gbuf_bypass=(True, ) * 3, sw_solve_loopblocking=True, ntops=2**30) # Cost. self.cost = Cost(mac_op=1, mem_hier=(200, 6, 2, 1), noc_hop=50, unit_static=50) # Partition occupation. self.part_occ = 0.91