tHub.
aboutsummaryrefslogtreecommitdiffstats
path: root/ecrts14/topology.py
blob: 099d3a316df156de7113ce206c6651d8c6e93bff (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#!/usr/bin/env python

#import os
#import re
#import fnmatch
#import shutil as sh
#import sys
#import csv
#from optparse import OptionParser
#
#from machines import machines

import numpy as np


class Topology:
    ncpus, root, leaves, dist_mat = 0, None, None, None
    levels = ['L1', 'L2', 'L3', 'MEM', 'SYSTEM']
    overhead = None

    class Node:
        idx, name, parent, children = 0, 'Unk', None, None
        def __init__(self, idx, name, parent = None):
            self.idx = idx
            self.name = name
            self.parent = parent
            self.children = []
#        def __repr__(self):
#            return self.name + '_' + str(self.idx)

    def __build_level_above(self, machine, l, child_nodes):
        key = 'n' + l
        if key in machine:
            cluster_sz = machine[key]
        else:
            cluster_sz = 1
        nchildren = len(child_nodes)
        nodes = [self.Node(idx, l) for idx in range(nchildren/cluster_sz)]
        for i in range(len(child_nodes)):
            child_nodes[i].parent = nodes[i/cluster_sz]
            nodes[i/cluster_sz].children.append(child_nodes[i])
        return nodes

    def __find_dist(self, a, b):
        if a != b:
            # pass-through (ex. as CPU is to private L1)
            if len(a.parent.children) == 1:
                return self.__find_dist(a.parent, b.parent)
            else:
                return 1 + self.__find_dist(a.parent, b.parent)
        return 0

    def __build_dist_matrix(self):
        dist_mat = np.empty([self.ncpus, self.ncpus], int)
        for i in range(self.ncpus):
            for j in range(i, self.ncpus):
                dist_mat[i,j] = dist_mat[j,i] = self.__find_dist(self.leaves[i], self.leaves[j])
        return dist_mat

    def __init__(self, machine):
        self.ncpus = machine['sockets']*machine['cores_per_socket']

        self.machine = machine

        # build the Topology bottom up
        self.leaves = [self.Node(idx, 'CPU') for idx in range(self.ncpus)]
        nodes = self.leaves
        for l in self.levels:
            nodes = self.__build_level_above(machine, l, nodes)
        self.root = nodes

        self.dist_mat = self.__build_dist_matrix()


#    def __repr_level(self, node, stem, buf):
#        spacing = 3
#        buf += stem + node.name + '_' + str(node.idx) + '\n'
#        for c in node.children:
#            buf = self.__repr_level(c, stem + ' '*spacing, buf)
#        return buf

#    def __repr__(self):
#        buf = self.__repr_level(self.root[0], '', '')
#        return buf

    def max_wss(self):
        # returns the maximum amount of data a CPU
        # can store in its cache for a task on a
        # __single socket__

        # cache levels in reverse order
        levels = ['L3', 'L2', 'L1']

        size = 0
        if self.machine['inclusive'] == 1: