-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbgqshared.py
132 lines (112 loc) · 4.95 KB
/
bgqshared.py
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
#!/usr/bin/env python
import sys
import ast
from collections import defaultdict
Dim = [4,4,4,4,2] # torus dimensions
# take a node, and return a five-tuple representing the coordinates
def convertNodeToCoords(nodeId):
eVal = nodeId / 1024
remainder = nodeId % 1024
dVal = remainder / 64
remainder = remainder % 64
cVal = remainder / 16
remainder = remainder % 16
bVal = remainder / 4
aVal = remainder % 4
return (aVal, bVal, cVal, dVal, eVal)
#reads nodes (as 5-tuples) from file passed in as command line arg
def readNodeSet(file):
list = []
with open(file) as f:
for line in f.readlines():
list.append(ast.literal_eval(line))
return list
def addLinksForward(source, index, numHops, linkSet):
last = source
for i in range(1, numHops+1):
oneHopForward = source[0:index] + (source[index]+i,) + source[index+1:len(source)]
linkSet[(last,oneHopForward)] += 1
last = oneHopForward
def addLinksBackward(source, index, numHops, linkSet):
last = source
for i in range(1, numHops+1):
oneHopBackward = source[0:index] + (source[index]-i,) + source[index+1:len(source)]
linkSet[(last,oneHopBackward)] += 1
last = oneHopBackward
#index is which of the five dimensions (A, B, C, D, E) we are moving in
#source and dest are the source and dest nodes (a five-tuple; A, B, C, D, E)
#linkSet is a dictionary; we going to count all links encountered on this move
def moveDirection(index, source, dest, linkSet):
global Dim
sI = source[index]
dI = dest[index]
dist = abs(sI-dI)
if dist <= Dim[index]/2 and sI <= dI: # do not use wraparound; already going forward
addLinksForward(source, index, dist, linkSet)
elif dist <= Dim[index]/2 and dI < sI: # do not use wraparound; must reverse direction
addLinksBackward(source, index, dist, linkSet)
else: # need to use wraparound
if sI < dI:
# two recursive calls to make two backward moves, then add wraparound link
start = source
end = source[0:index] + (dest[index],) + source[index+1:len(source)]
smallEnd = source[0:index] + (0,) + source[index+1:len(source)]
moveDirection(index, start, smallEnd, linkSet)
largeEnd = source[0:index] + (Dim[index]-1,) + source[index+1:len(source)]
moveDirection(index, largeEnd, end, linkSet)
linkSet[(smallEnd, largeEnd)] += 1 # this adds the wraparound link
else:
# two recursive calls to make two forward moves, then add wraparound link
start = source[0:index] + (dest[index],) + source[index+1:len(source)]
end = source
smallEnd = source[0:index] + (0,) + source[index+1:len(source)]
moveDirection(index, smallEnd, start, linkSet)
largeEnd = source[0:index] + (Dim[index]-1,) + source[index+1:len(source)]
moveDirection(index, end, largeEnd, linkSet)
linkSet[(largeEnd, smallEnd)] += 1 # this adds the wraparound link
# return progress up to this point
return source[0:index] + (dest[index],) + source[index+1:len(source)]
#route from all nodes in a node list to all other nodes in that node list
#assumes all-to-all communication exists
def doRouting(nodeList, linkSet):
for source in nodeList:
for dest in nodeList:
if source == dest:
continue
#move in each of the five directions, one at a time. After a move in dimension i, source matches dest in dimension i
#order is sorted by decreasing dimension; ties broken lexicographically
sortedDim = sorted(list(enumerate(Dim)),key=lambda x: x[1],reverse=True)
for i in range(len(Dim)):
newSource = moveDirection(sortedDim[i][0], source, dest, linkSet)
#compute set of links that the first job uses
def determineLinkSet(nodeListJobOne):
linksJobOne = defaultdict(lambda: 0) #all entries initialized to zero
doRouting(nodeListJobOne, linksJobOne)
return linksJobOne
#compute set of links that the second job causes
def determineLinkConflicts(nodeListJobTwo, linksJobOne):
linksJobTwo = defaultdict(lambda: 0) #all entries initialized to zero
conflictedLinks = [] #list holding every conflicted link
doRouting(nodeListJobTwo, linksJobTwo)
for i in linksJobOne:
if i in linksJobTwo:
conflictedLinks.append((i,linksJobOne[i]+linksJobTwo[i]))
return linksJobTwo, conflictedLinks
def main(argv1,argv2):
nodeListJobOne = readNodeSet(argv1)
nodeListJobTwo = readNodeSet(argv2)
linksJobOne = determineLinkSet(nodeListJobOne)
linksJobTwo, conflictLinks = determineLinkConflicts(nodeListJobTwo, linksJobOne)
print ""
sum = 0
for i in conflictLinks:
sum += 1
print i
print "total number of conflicted links", sum
#sanity checks
print "Nodes Job 1: ", len(nodeListJobOne), " Nodes Job 2: ", len(nodeListJobTwo), " Shared Nodes (should be 0): ", len(set(nodeListJobOne) & set(nodeListJobTwo))
return len(conflictLinks)
#tuples from job1 and job2 should be passed as command line arguments
#where each file contains 1 5-tuple per line
if __name__ == "__main__":
sys.exit(main(sys.argv[1], sys.argv[2]))