mec-UMN / HISIM

MIT License
12 stars 3 forks source link

Wrapper Script + User Feedback (PPA.csv, relative paths, system exits) #3

Closed jzhou1318 closed 2 months ago

jzhou1318 commented 2 months ago

I've been trying to integrate HiSim with a design space explorer ArchGym and have some user feedback.

  1. I've created a wrapper script (copy-pasted below) that I think would be useful for others and would love to see it up-streamed. The script:

    1. Wraps and re-factors the analy_model.py file. This is necessary for external tools to best interact with HiSim
    2. Changed how the PPA.csv file is generated. When the HiSim model is first instantiated, the header for the file is written; every result that's generated by this instantiation of the HiSim model is added afterwards.
    3. Label the PPA.csv results. The original PPA.csv header was incomplete so I did my best to fill in the blanks and add correct units to each label. Please let me know if this assignment is correct as I assigned the labels/units based on print statements, comments, and figures in the paper.
    4. I am working on adding setter functions to the script. For now, I only have set_num_pe. This is useful when doing design space exploration. Combined with the new way to generate PPA.csv, all results are congregated in one spot for easy analysis. A small example is left at the end of the script.
  2. PPA.csv confusion

    1. As mentioned before, I had to manually trace what values added to the results_list correspond with what metric and the units of the metric. Would appreciate more comments in the code next to each results_list.append() call.
    2. If not every value in the header would be logged for every combination of inputs, either a) use 'NaN' to signify (I did this with thermal values) or generate a new header to use. This would streamline and standardize results analysis.
    3. It seems not all printed values are logged in the PPA.csv, is this intentional? For example, leakage power from compute_imc is printed but logged.
    4. I also added simulation timing to the CSV file rather than just printing them.
  3. Change relative to absolute paths for more streamlined integration with other codebases. I changed aib_2_5d.py and util_mapping.py in my local version.

  4. Change system exits to throwing exceptions. Ending the entire program during design space exploration when encountering a bad configuration is unideal. I'm working on implementing this in my local version (twice in util_mapping.py and once in analy_model.py, planning to just return a list with a single entry as the error string)

Edit: I've forked version 1 of the repo and implemented many changes there https://github.com/jzhou1318/HISIM

import os
import shutil
import csv
import time
import argparse
import sys
from Module_Compute.functions import imc_analy
from Module_Thermal.thermal_model import thermal_model
from Module_Network.network_model import network_model
from Module_Compute.compute_IMC_model import compute_IMC_model
from Module_AI_Map.util_chip.util_mapping import model_mapping, load_ai_network,smallest_square_greater_than
from Module_Network.aib_2_5d import  aib
from itertools import chain
import pandas as pd
if not os.path.exists('./Debug/to_interconnect_analy'):
    os.makedirs('./Debug/to_interconnect_analy')
if not os.path.exists('./Results/result_thermal'):
    os.makedirs('./Results/result_thermal')
if os.path.exists('./Results/result_thermal/1stacks'):
    shutil.rmtree('.//Results/result_thermal/1stacks')
if not os.path.exists('./Results'):
    os.makedirs('./Results')
os.makedirs('.//Results/result_thermal/1stacks')

class HiSimModel:

    def __init__(
        self,
        chip_architect = "M3D", # string | hardware architecture                        - M3D,M2D,H2_5D,H2_5D_3D
        xbar_size = 512,        # int    | crossbar size                                - 64,128,256,512,1024
        N_tile = 324,           # int    | number of tiles in tier                      - 4,9,16,25,36,49                     
        N_crossbar = 1,         # int    | number of crossbars in one PE                - 4, 9, 16
        N_pe = 16,              # int    | number of PEs in one tile - 4,9,16,25,36
        quant_weight = 8,       # int    | precision of quantized weight of AI model
        quant_act = 8,          # int    | precision fo quantized activation of AI model
        freq_computing = 1,     # float  | computing unit operation frequency
        fclk_noc = 1,           # float  | network data communication operation frequency
        tsv_pitch = 10,         # float  | TSV pitch (um)
        N_tier = 4,             # int    | number of tiers                              - 2,3,4,5,6,7,8,9,10 
        volt = 0.5,             # float  | operating voltage
        placement_method = 5,   # int    | computing tile placement
        percent_router = 0.5,   # float  | percentage of router dedicated to 3D comm LOOK INTO THIS WHAT
        compute_validate = False,       # | validate compute model with neurosim 
        W2d = 32,               # int    | number of links of 2D NoC
        router_times_scale = 1, # int    | scaling factor for time of: trc, tva, tsa, tst, tl, tenq
        ai_model = "vit",       # string | AI model
        thermal = True,                 # | run thermal simulation
        ppa_filepath ="./Results/PPA.csv"  
    ):
        if chip_architect == "H2_5D":
            self.placement_method = 1
        else:
            self.placement_method = placement_method

        # never used 
        self.relu=True
        self.sigmoid=False

        self.chip_architect = chip_architect
        self.xbar_size = xbar_size
        self.N_tile = N_tile
        self.N_crossbar = N_crossbar
        self.N_pe = N_pe
        self.quant_weight = quant_weight
        self.quant_act = quant_act
        self.freq_computing = freq_computing
        self.fclk_noc = fclk_noc
        self.tsv_pitch = tsv_pitch
        self.N_tier = N_tier
        self.volt = volt
        self.placement_method = placement_method
        self.percent_router = percent_router
        self.compute_validate = compute_validate
        self.W2d = W2d
        self.router_times_scale = router_times_scale
        self.ai_model = ai_model
        self.thermal = thermal

        self.filename_results = ppa_filepath

        self.csv_header = [
                                'freq_core (GHz)',
                                'freq_noc (GHz)',
                                'Xbar_size',
                                'N_tile', 
                                'N_pe',
                                'N_tile(real)',
                                'N_tier(real)',
                                'W2d',
                                'W3d',
                                'Computing_latency (ns)',
                                'Computing_energy (pJ)',
                                'compute_area (um2)',
                                'compute_area per tier (mm2)',
                                'chip_Architecture',

                                '2d NoC latency (ns)',
                                '3d NoC latency (ns)',
                                '2.5d NoC latency (ns)',
                                'network_latency (ns)',
                                '2d NoC energy (pJ)',
                                '3d NoC energy (pJ)',
                                '2.5d NoC energy (pJ)',
                                'network_energy (pJ)',

                                'rcc (??)',
                                'compute_power (W)',
                                '2D_3D_NoC_power (W)',
                                '2_5D_power (W)',
                                '2d_3d_router_area (mm2)',

                                'placement_method',
                                'percent_router',

                                'peak_temperature (C)',

                                'thermal simulation time (s)',
                                'networking simulation time (s)',
                                'computing simulation time (s)',
                                'total simulation time (s)'

                            ]

        with open(self.filename_results, 'w', newline='') as csvfile:
                # Create a csv writer object
                writer = csv.writer(csvfile)
                # writer.writerow(["freq_core","freq_noc","Xbar_size","N_tile","N_pe","N_tier(chiplet)","W2d","W3d","Computing_latency", "Computing_energy","chip_area","network_latency","network_energy","peak_temperature"])
                # writer.writerow(['freq_core','freq_noc','Xbar_size','N_tile', 'N_pe','N_tile(real)','N_tier(real)','W2d','W3d','Computing_latency','Computing_energy','compute_area','chip_area','chip_Architecture','2d NoC latency','3d NoC latency','2.5d NoC latency','network_latency','2d NoC energy','3d NoC energy','2.5d NoC energy','network_energy','rcc','TFLOPS,compute_power','2D_3D_NoC_power','2_5D_power,''2d_3d_router_area','peak_temperature','placement_method','percent_router'])
                writer.writerow(self.csv_header)

    def set_num_pe(self, N_pe):
        self.N_pe = N_pe

    def run_model(self):

        result_list=[]

        result_list.append(self.freq_computing)
        result_list.append(self.fclk_noc)
        result_list.append(self.xbar_size)
        result_list.append(self.N_tile)
        result_list.append(self.N_pe)

        print("=========================================start HISIM simulation ========================================= ","\n")
        start = time.time()       
        #---------------------------------------------------------------------#
        #                                                                     #
        #     Mapping: from AI model -> hardware mapping                      #
        #                                                                     #
        #---------------------------------------------------------------------#
        network_params = load_ai_network(self.ai_model)                 #Load AI network parameters from the network csv file
        print("----------------------------------------------------","\n")
        print("start mapping ",self.ai_model,"\n")

        #---------------------------------------------------------------------#
        #                                                                     #
        #     Configuration of the AI models mapped to architecture           # 
        #                                                                     #
        #---------------------------------------------------------------------#
        filename = "./Debug/to_interconnect_analy/layer_inform.csv"
        tiles_each_tier = [0] * self.N_tier
        total_tiles_real = model_mapping(
            filename,
            self.placement_method,
            network_params,
            self.quant_act,
            self.xbar_size,
            self.N_crossbar,
            self.N_pe,
            self.quant_weight,
            self.N_tile,
            self.N_tier,
            tiles_each_tier)

        #Placement Method 1: Number of tiers are determined based on the mapping and user defined number of tiles per tier
        #Placement Method 5: Number of tiles per tier are determined based on the mapping and user defined number of tiers
        if self.placement_method == 5:
            N_tier_real = self.N_tier
            #Average of tiles mapped per tier                    
            N_tile_real=smallest_square_greater_than(max(tiles_each_tier))
        else:
            N_tile_real = self.N_tile 
            #Total number of tiers or chiplets                          
            if total_tiles_real % self.N_tile==0:
                N_tier_real=int(total_tiles_real//self.N_tile)       
            else:
                N_tier_real=int(total_tiles_real//self.N_tile)+1     
        result_list.append(N_tile_real)                         

        if N_tier_real>4:
            print("Alert!!! too many number of tiers")
            return ["Alert!!! too many number of tiers"]

        result_list.append(N_tier_real)

        #---------------------------------------------------------------------#
        #                                                                     #
        #     Computing: generate PPA for IMC/GPU/CPU/ASIC computing units    #
        #                                                                     #
        #---------------------------------------------------------------------#
        compute_results = compute_IMC_model(self.compute_validate,
                                            self.xbar_size,
                                            self.volt, 
                                            self.freq_computing,
                                            self.quant_act,
                                            self.quant_weight,
                                            self.N_crossbar,
                                            self.N_pe,
                                            N_tier_real,
                                            self.N_tile,
                                            result_list, 
                                            network_params)

        N_tier_real,computing_data,area_single_tile,volt,total_model_L,result_list,out_peripherial,A_peri = compute_results
        end_computing = time.time()
        print("--------------------------------------------------------")
        print("----------computing performance done--------------------")

        #---------------------------------------------------------------------#
        #                                                                     #
        #     Network: generate PPA for NoC/NoP (2D/2.5D/3D/heterogeneous)    #
        #                                                                     #
        #---------------------------------------------------------------------#

        network_results = network_model(
                                        N_tier_real,
                                        self.N_tile,
                                        self.N_tier,
                                        computing_data,
                                        self.placement_method,
                                        self.percent_router,
                                        self.chip_architect,
                                        self.tsv_pitch,
                                        area_single_tile,
                                        result_list,
                                        self.volt,
                                        self.fclk_noc,
                                        total_model_L,
                                        self.router_times_scale)
        chiplet_num,tier_2d_hop_list_power,tier_3d_hop_list_power,single_router_area,mesh_edge,layer_aib_list,result_list = network_results
        end_noc = time.time()
        print("\n")
        result_list.append(self.placement_method)
        result_list.append(self.percent_router)

        #---------------------------------------------------------------------------------#
        #                                                                                 #
        #     Thermal: generate temperature of the chip (based on power,area)             #
        #                                                                                 #
        #---------------------------------------------------------------------------------#
        sim_name="Densenet_placement_1"
        # thermal_model function will start the simulation for generating the temperature results based on the power and area of the different blocks of the chip
        if self.thermal:
            print("----------thermal analysis start--------------------")

            peak_temp = thermal_model(
                            self.thermal,
                            self.chip_architect,
                            chiplet_num,
                            self.N_tile,
                            self.placement_method,
                            tier_2d_hop_list_power,
                            tier_3d_hop_list_power,
                            area_single_tile,
                            single_router_area,
                            mesh_edge,
                            sim_name,
                            layer_aib_list)
        else:
            peak_temp = 'NaN'

        end_thermal = time.time()

        result_list.append(peak_temp)
        result_list.append(end_thermal - end_noc) # thermal time

        result_list.append(end_noc - end_computing) # networking time
        result_list.append(end_computing - start) # computing time
        result_list.append(end_thermal - start) # whole sim

        with open(self.filename_results, 'a', newline='') as csvfile:
            # Create a csv writer object
            writer = csv.writer(csvfile)
            writer.writerow(result_list)

        return result_list

    def results_dict(self, results_list):
        return dict(zip(self.csv_header, results_list))

hisim = HiSimModel(
            chip_architect = "M3D",
            xbar_size = 1024,
            N_tile = 100,
            N_pe = 9,
            N_tier = 3,
            freq_computing = 1,
            fclk_noc = 1,
            placement_method = 5,
            router_times_scale = 1,
            percent_router = 1,
            tsv_pitch = 5,
            W2d = 32,
            ai_model = 'vit',
            thermal = False
        )

df = pd.read_csv('./num_pe.csv')
num_pes = df['num_pe']

for num_pe in num_pes:
    print(num_pe)
    hisim.set_num_pe(num_pe)
    results = hisim.run_model()
pragnyan948 commented 2 months ago

Hey Jennifer,

Thanks for the user feedback.

I have added you to the HISIM development repo that we internally use. Please commit your changes there in the future for easier integration. I will integrate the current changes from your forked location this time.

I will clarify the PPA.csv queries in the issue #4 response.

Regards, Pragnya