<commit_before>""" $lic$
Copyright (C) 2016-2017 by The Board of Trustees of Stanford University

This program is free software: you can redistribute it and/or modify it under
the terms of the Modified BSD-3 License as published by the Open Source
Initiative.

If you use this program in your research, we request that you reference the
TETRIS paper ("TETRIS: Scalable and Efficient Neural Network Acceleration with
3D Memory", in ASPLOS'17. April, 2017), and that you send us a citation of your
work.

This program is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. See the BSD-3 License for more details.

You should have received a copy of the Modified BSD-3 License along with this
program. If not, see <https://opensource.org/licenses/BSD-3-Clause>.
"""

import itertools
from collections import OrderedDict, MutableMapping

from . import LoopEnum as le
from . import MemHierEnum as me
from . import Util
from .DataLayout import DataLayout
from .Layer import ConvLayer
from .Network import Network
from .Scheduling import SchedulingResult

class SegmentScheduleTiming(object):
    ''' Timing information of a segment schedule. '''

    class SpatialScheduleTiming(object):
        ''' Time information of a spatial schedule. '''

        def __init__(self, head=0, tail=0, tail_split=float('inf')):
            self.head = head
            self.tail = tail
            self.tail_split = tail_split

        def reset_tail(self, tail, tail_split):
            ''' Add current tail to head and reset tail. '''
            self.head += self.tail
            self.tail = tail
            self.tail_split = tail_split

        def incr_tail(self, tail):
            ''' Increment tail. '''
            self.tail += tail

        def time(self):
            ''' Total time. '''
            return self.head + self.tail

        def split_time(self, tbat_split):
            ''' Time with split tail. '''
            return self.head + self.tail / self.tail_split / tbat_split

        def __repr__(self):
            return '{}(head={}, tail={}, tail_split={})' \
                    .format(self.__class__.__name__, self.head, self.tail,
                            self.tail_split)


    def __init__(self, seg_idx, sp_timing_list=None, tbat_split=float('inf'),
                 last_sched_seq=None):

        # Segment index.
        self.seg_idx = seg_idx

        # A list of spatial schedule timing info in this segment.
        self.sp_timing_list = sp_timing_list if sp_timing_list else []

        # The top BAT loop factor, shared by all layers in the segment.
        self.tbat_split = tbat_split

        # Schedule sequence number of the last added schedule.
        self.last_sched_seq = last_sched_seq if last_sched_seq else tuple()

    def time(self):
        ''' The total time of the segment schedule. '''

        # The longest spatial schedule in the segment.
        max_idx, max_sp_timing = max(enumerate(self.sp_timing_list),
                                     key=lambda tpl: tpl[1].time())

        t = 0

        # Segment pipeline filling/draining time.
        t += sum(sp_timing.split_time(self.tbat_split)
                 for sp_timing in self.sp_timing_list[:-1])
        # Segment critical stage time (minus filling/draining time).
        t += max_sp_timing.time()

        if max_idx != len(self.sp_timing_list) - 1:
            # Minus the double counted part.
            t -= max_sp_timing.split_time(self.tbat_split)

        return t

    def critical_time(self):
        ''' The critical pipeline stage time of the segment schedule. '''
        return max(sp_timing.time() for sp_timing in self.sp_timing_list)

    def add(self, layer, sched_result):
        ''' Add the SchedulingResult of a new layer. '''

        # Schedule sequence number.
        sched_seq = sched_result.sched_seq

        # Loop blocking scheme: blocking factors and orders.
        lp_ts = [None] * le.NUM
        lp_ts[le.IFM] = sched_result.dict_loop['ti']
        lp_ts[le.OFM] = sched_result.dict_loop['to']
        lp_ts[le.BAT] = sched_result.dict_loop['tb']
        bl_ts = list(zip(*lp_ts))
        bl_ords = sched_result.dict_loop['orders']

        # Check sched_seq, and find the incremented dimension.
        if sched_seq[0] != self.seg_idx:
            raise ValueError('SegmentScheduleTiming: sched_seq {} does not '
                             'belong to segment {}'
                             .format(sched_seq, self.seg_idx))<commit_msg>[NNDataflowScheme] Fix a bug in pipeline time.<commit_after>""" $lic$
Copyright (C) 2016-2017 by The Board of Trustees of Stanford University

This program is free software: you can redistribute it and/or modify it under
the terms of the Modified BSD-3 License as published by the Open Source
Initiative.

If you use this program in your research, we request that you reference the
TETRIS paper ("TETRIS: Scalable and Efficient Neural Network Acceleration with
3D Memory", in ASPLOS'17. April, 2017), and that you send us a citation of your
work.

This program is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. See the BSD-3 License for more details.

You should have received a copy of the Modified BSD-3 License along with this
program. If not, see <https://opensource.org/licenses/BSD-3-Clause>.
"""

import itertools
from collections import OrderedDict, MutableMapping

from . import LoopEnum as le
from . import MemHierEnum as me
from . import Util
from .DataLayout import DataLayout
from .Layer import ConvLayer
from .Network import Network
from .Scheduling import SchedulingResult

class SegmentScheduleTiming(object):
    ''' Timing information of a segment schedule. '''

    class SpatialScheduleTiming(object):
        ''' Time information of a spatial schedule. '''

        def __init__(self, head=0, tail=0, tail_split=float('inf')):
            self.head = head
            self.tail = tail
            self.tail_split = tail_split

        def reset_tail(self, tail, tail_split):
            ''' Add current tail to head and reset tail. '''
            self.head += self.tail
            self.tail = tail
            self.tail_split = tail_split

        def incr_tail(self, tail):
            ''' Increment tail. '''
            self.tail += tail

        def time(self):
            ''' Total time. '''
            return self.head + self.tail

        def split_time(self, tbat_split):
            ''' Time with split tail. '''
            return self.head + self.tail / self.tail_split / tbat_split

        def __repr__(self):
            return '{}(head={}, tail={}, tail_split={})' \
                    .format(self.__class__.__name__, self.head, self.tail,
                            self.tail_split)


    def __init__(self, seg_idx, sp_timing_list=None, tbat_split=float('inf'),
                 last_sched_seq=None):

        # Segment index.
        self.seg_idx = seg_idx

        # A list of spatial schedule timing info in this segment.
        self.sp_timing_list = sp_timing_list if sp_timing_list else []

        # The top BAT loop factor, shared by all layers in the segment.
        self.tbat_split = tbat_split

        # Schedule sequence number of the last added schedule.
        self.last_sched_seq = last_sched_seq if last_sched_seq else tuple()

    def time(self):
        ''' The total time of the segment schedule. '''

        # The longest spatial schedule in the segment.
        max_sp_timing = max(self.sp_timing_list, key=lambda spt: spt.time())

        t = 0

        # Segment pipeline filling/draining time.
        t += sum(sp_timing.split_time(self.tbat_split)
                 for sp_timing in self.sp_timing_list)
        # Segment critical stage time (minus filling/draining time).
        t += max_sp_timing.time() - max_sp_timing.split_time(self.tbat_split)

        return t

    def critical_time(self):
        ''' The critical pipeline stage time of the segment schedule. '''
        return max(sp_timing.time() for sp_timing in self.sp_timing_list)

    def add(self, layer, sched_result):
        ''' Add the SchedulingResult of a new layer. '''

        # Schedule sequence number.
        sched_seq = sched_result.sched_seq

        # Loop blocking scheme: blocking factors and orders.
        lp_ts = [None] * le.NUM
        lp_ts[le.IFM] = sched_result.dict_loop['ti']
        lp_ts[le.OFM] = sched_result.dict_loop['to']
        lp_ts[le.BAT] = sched_result.dict_loop['tb']
        bl_ts = list(zip(*lp_ts))
        bl_ords = sched_result.dict_loop['orders']

        # Check sched_seq, and find the incremented dimension.
        if sched_seq[0] != self.seg_idx:
            raise ValueError('SegmentScheduleTiming: sched_seq {} does not '
                             'belong to segment {}'
                             .format(sched_seq, self.seg_idx))
{'fraction_non_alphanumeric': 0.08669689262412916, 'fraction_numerical': 0.005418555789008073, 'mean_word_length': 2.451908396946565, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '498166', 'n_tokens_mistral': 2609, 'n_tokens_neox': 2509, 'n_words': 862}