mirror of
https://github.com/RRZE-HPC/OSACA.git
synced 2025-12-16 00:50:06 +01:00
improved TP scheduling, port binding output added, updated displaying of file path
This commit is contained in:
171
EUsched.py
171
EUsched.py
@@ -5,6 +5,7 @@ import os
|
||||
import math
|
||||
import ast
|
||||
from Params import *
|
||||
from operator import add
|
||||
import pandas as pd
|
||||
|
||||
class Scheduler(object):
|
||||
@@ -27,16 +28,61 @@ class Scheduler(object):
|
||||
self.df = pd.read_csv(currDir+'data/'+arch.lower()+'_data.csv', quotechar='"', converters={'ports':ast.literal_eval})
|
||||
|
||||
|
||||
def schedule(self):
|
||||
'''
|
||||
Schedules Instruction Form list and calculates port bindings.
|
||||
|
||||
Returns
|
||||
-------
|
||||
(str, [int, ...])
|
||||
A tuple containing the graphic output of the schedule as string and
|
||||
the port bindings as list of ints.
|
||||
'''
|
||||
sched = self.get_head()
|
||||
# Initialize ports
|
||||
# groups = [[] for x in range(len(set(portOccurances))-1)]
|
||||
occ_ports = [[0]*self.ports for x in range(len(self.instrList))]
|
||||
# occ_ports = [[0]*self.ports]*len(self.instrList)
|
||||
port_bndgs = [0]*self.ports
|
||||
# Check if there's a port occupation stored in the CSV, otherwise leave the
|
||||
# occ_port list item empty
|
||||
for i,instrForm in enumerate(self.instrList):
|
||||
try:
|
||||
searchString = instrForm[0]+'-'+self.get_operand_suffix(instrForm)
|
||||
entry = self.df.loc[lambda df: df.instr == searchString,'TP':'ports']
|
||||
tup = entry.ports.values[0]
|
||||
if(len(tup) == 1 and tup[0][0] == -1):
|
||||
raise IndexError()
|
||||
except IndexError:
|
||||
# Instruction form not in CSV
|
||||
sched += self.get_line(occ_ports[i], '* '+instrForm[-1])
|
||||
continue
|
||||
# Get the occurance of each port from the occupation list
|
||||
portOccurances = self.get_port_occurances(tup)
|
||||
# Get 'occurance groups'
|
||||
occuranceGroups = self.get_occurance_groups(portOccurances)
|
||||
# Calculate port dependent throughput
|
||||
TPGes = entry.TP.values[0]*len(occuranceGroups[0])
|
||||
for occGroup in occuranceGroups:
|
||||
for port in occGroup:
|
||||
occ_ports[i][port] = TPGes/len(occGroup)
|
||||
# Write schedule line
|
||||
sched += self.get_line(occ_ports[i], instrForm[-1])
|
||||
# Add throughput to total port binding
|
||||
port_bndgs = list(map(add, port_bndgs, occ_ports[i]))
|
||||
return (sched, port_bndgs)
|
||||
|
||||
|
||||
def schedule_FCFS(self):
|
||||
'''
|
||||
Schedules Instruction Form list via First Come First Serve algorithm.
|
||||
Schedules Instruction Form list for a single run with latencies.
|
||||
|
||||
Returns
|
||||
-------
|
||||
(str, int)
|
||||
A tuple containing the graphic output as string and the total throughput time as int.
|
||||
'''
|
||||
sched = ''
|
||||
sched = self.get_head()
|
||||
total = 0
|
||||
# Initialize ports
|
||||
occ_ports = [0]*self.ports
|
||||
@@ -70,6 +116,57 @@ class Scheduler(object):
|
||||
total += max(occ_ports)
|
||||
return (sched, total)
|
||||
|
||||
|
||||
def get_occurance_groups(self, portOccurances):
|
||||
'''
|
||||
Groups ports in groups by the number of their occurance and sorts
|
||||
groups by cardinality
|
||||
|
||||
Parameters
|
||||
----------
|
||||
portOccurances : [int, ...]
|
||||
List with the length of ports containing the number of occurances
|
||||
of each port
|
||||
|
||||
Returns
|
||||
-------
|
||||
[[int, ...], ...]
|
||||
List of lists with all occurance groups sorted by cardinality
|
||||
(smallest group first)
|
||||
'''
|
||||
groups = [[] for x in range(len(set(portOccurances))-1)]
|
||||
for i,groupInd in enumerate(range(min(list(filter(lambda x: x > 0, portOccurances))),max(portOccurances)+1)):
|
||||
for p, occurs in enumerate(portOccurances):
|
||||
if groupInd == occurs:
|
||||
groups[i].append(p)
|
||||
# Sort groups by cardinality
|
||||
groups.sort(key=len)
|
||||
return groups
|
||||
|
||||
|
||||
def get_port_occurances(self, tups):
|
||||
'''
|
||||
Returns the number of each port occurance for the possible port
|
||||
occupations
|
||||
|
||||
Parameters
|
||||
----------
|
||||
tups : ((int, ...), ...)
|
||||
Tuple of tuples of possible port occupations
|
||||
|
||||
Returns
|
||||
-------
|
||||
[int, ...]
|
||||
List in the length of the number of ports for the current architecture,
|
||||
containing the amount of occurances for each port
|
||||
'''
|
||||
ports = [0]*self.ports
|
||||
for tup in tups:
|
||||
for elem in tup:
|
||||
ports[elem] += 1
|
||||
return ports
|
||||
|
||||
|
||||
def test_ports_FCFS(self, occ_ports, needed_ports):
|
||||
'''
|
||||
Test if current configuration of ports is possible and returns boolean
|
||||
@@ -92,12 +189,21 @@ class Scheduler(object):
|
||||
return False
|
||||
return True
|
||||
|
||||
def schedule_Tomasulo(self):
|
||||
|
||||
def get_report_info(self):
|
||||
'''
|
||||
Not implement yet. Schedules Instruction Form list via Tomasulo algorithm.
|
||||
Creates Report information including all needed annotations.
|
||||
|
||||
Returns
|
||||
-------
|
||||
str
|
||||
String containing the report information
|
||||
'''
|
||||
print('Scheduling with Tomasulo algorithm...')
|
||||
return ''
|
||||
analysis = 'Throughput Analysis Report\n'+('-'*26)+'\n'
|
||||
annotations = ( '* - No information for this instruction in database\n'
|
||||
'\n')
|
||||
return analysis+annotations
|
||||
|
||||
|
||||
def get_head(self):
|
||||
'''
|
||||
@@ -108,25 +214,23 @@ class Scheduler(object):
|
||||
str
|
||||
String containing the header
|
||||
'''
|
||||
analysis = 'Throughput Analysis Report\n'+('-'*26)+'\n'
|
||||
annotations = ( '* - No information for this instruction in database\n'
|
||||
'\n')
|
||||
horizLine = '-'*6*self.ports+'-\n'
|
||||
horizLine = '-'*7*self.ports+'-\n'
|
||||
portAnno = ' '*(math.floor((len(horizLine)-24)/2))+'Ports Pressure in cycles'+' '*(math.ceil((len(horizLine)-24)/2))+'\n'
|
||||
portLine = ''
|
||||
for i in range(0,self.ports):
|
||||
portLine += '| {} '.format(i)
|
||||
portLine += '| {} '.format(i)
|
||||
portLine += '|\n'
|
||||
head = analysis+annotations+portAnno+portLine + horizLine
|
||||
head = portAnno+portLine+horizLine
|
||||
return head
|
||||
|
||||
|
||||
def get_line(self, occ_ports, instrName):
|
||||
'''
|
||||
Create line with port occupation for output.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
occ_ports : (int)
|
||||
occ_ports : (int, ...)
|
||||
Integer tuple containing needed ports
|
||||
instrName : str
|
||||
Name of instruction form for output
|
||||
@@ -138,11 +242,39 @@ class Scheduler(object):
|
||||
'''
|
||||
line = ''
|
||||
for i in occ_ports:
|
||||
cycles = ' ' if (i == 0) else float(i)
|
||||
line += '| '+str(cycles)+' '
|
||||
cycles = ' ' if (i == 0) else '%.2f' % float(i)
|
||||
line += '| '+cycles+' '
|
||||
line += '| '+instrName+'\n'
|
||||
return line
|
||||
|
||||
|
||||
def get_port_binding(self, port_bndg):
|
||||
'''
|
||||
Creates port binding out of scheduling result.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
port_bndg : [int, ...]
|
||||
Integer list containing port bindings
|
||||
|
||||
Returns
|
||||
-------
|
||||
str
|
||||
String containing the port binding graphical output
|
||||
'''
|
||||
header = 'Port Binding in Cycles Per Iteration:\n'
|
||||
horizLine = '-'*10+'-'*6*self.ports+'\n'
|
||||
portLine = '| Port |'
|
||||
for i in range(0, self.ports):
|
||||
portLine += ' {} |'.format(i)
|
||||
portLine += '\n'
|
||||
cycLine = '| Cycles |'
|
||||
for i in range(len(port_bndg)):
|
||||
cycLine += ' {} |'.format(round(port_bndg[i], 2))
|
||||
cycLine += '\n'
|
||||
binding = header+horizLine+portLine+horizLine+cycLine+horizLine
|
||||
return binding
|
||||
|
||||
|
||||
def get_operand_suffix(self, instrForm):
|
||||
'''
|
||||
@@ -191,8 +323,9 @@ if __name__ == '__main__':
|
||||
['jb',Parameter('LBL'),'jb 400bc2 <main+0x62>']
|
||||
]
|
||||
|
||||
sched = Scheduler('skl', data)
|
||||
print(sched.get_head(),end='')
|
||||
output,total = sched.schedule_FCFS()
|
||||
sched = Scheduler('ivb', data)
|
||||
output,binding = sched.schedule()
|
||||
print(sched.get_port_binding(binding))
|
||||
print(sched.get_report_info(),end='')
|
||||
print(output)
|
||||
print('Total number of estimated throughput: '+str(total))
|
||||
print('Block Throughput: {}'.format(round(max(binding),2)))
|
||||
|
||||
10
osaca.py
10
osaca.py
@@ -610,7 +610,7 @@ class Osaca(object):
|
||||
ws = ' '*(len(horizLine)-23)
|
||||
# Write general information about the benchmark
|
||||
output = ( '--'+horizLine+'\n'
|
||||
'| Analyzing of file:\t'+os.getcwd()+'/'+self.filepath+'\n'
|
||||
'| Analyzing of file:\t'+os.path.abspath(self.filepath)+'\n'
|
||||
'| Architecture:\t\t'+self.arch+'\n'
|
||||
'| Timestamp:\t\t'+datetime.now().strftime('%Y-%m-%d %H:%M:%S')+'\n')
|
||||
|
||||
@@ -619,9 +619,11 @@ class Osaca(object):
|
||||
if(pr_sched):
|
||||
output += '\n\n'
|
||||
sched = Scheduler(self.arch, self.instrForms)
|
||||
schedOutput,totalTP = sched.schedule_FCFS()
|
||||
output += sched.get_head()+schedOutput
|
||||
output += 'Total number of estimated throughput: '+str(totalTP)
|
||||
schedOutput,portBinding = sched.schedule()
|
||||
binding = sched.get_port_binding(portBinding)
|
||||
output += sched.get_report_info()+'\n'+binding+'\n\n'+schedOutput
|
||||
blockTP = round(max(portBinding), 2)
|
||||
output += 'Total number of estimated throughput: '+str(blockTP)
|
||||
return output
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user