Commit 3a6da863 authored by mshahbaz's avatar mshahbaz
Browse files

initial commits

parents
import random, math
#random.seed(0)
class Port:
def __init__(self, ID):
self.id = ID
self.subscribe = set()
self.meta = set()
self.rate = 0
self.effective = 0
class Group:
def __init__(self, ID, name, ports, rate, P):
self.id = ID
self.name = name
self.ports = ports
self.rate = rate
self.meta = -1
#[effective, duplicate, extra_send, extra_recv]
self.groupRate = [len(ports)*rate, (len(ports)-1)*rate, 0, 0]
for i in ports:
P[i].subscribe.add(ID)
P[i].rate += rate
P[i].effective += rate
class MetaGroup:
def __init__(self, ID):
self.id = ID
self.ports = set()
self.groups = set()
self.rate = 0
self.metaRate = [0,0,0] #[effective, duplicate, extra]
# assign group G to meta-group M. P is all ports.
def Assign(group, meta, P, G):
if group.id in meta.groups:
error = 'group [%d] is already in meta-group [%d]'%(group.id, meta.id)
sys.exit(error)
for i in meta.ports - group.ports:
P[i].rate += group.rate
for i in group.ports - meta.ports:
P[i].rate += meta.rate
P[i].meta.add(meta.id)
group.groupRate[2] = len(meta.ports-group.ports)*group.rate
for i in meta.groups:
G[i].groupRate[2] += len(group.ports - meta.ports)*G[i].rate
G[i].groupRate[3] += len(G[i].ports - group.ports)*group.rate
group.groupRate[3] += len(group.ports - G[i].ports)*G[i].rate
group.meta = meta.id
meta.groups.add(group.id)
meta.ports.update(group.ports)
meta.rate += group.rate
meta.metaRate[0] += group.groupRate[0]
meta.metaRate[1] += group.groupRate[1]
meta.metaRate[2] = len(meta.ports)*meta.rate - meta.metaRate[0]
#meta.metaRate = metaRate(meta, G)
# remove group G from meta-group M. G is all groups, P is all ports.
def Remove(group, meta, P, G, M_empty):
if group.id not in meta.groups:
error = 'group [%d] is not in meta-group [%d]'%(group.id, meta.id)
sys.exit(error)
leaving = group.ports.copy()
for i in meta.groups:
if i != group.id:
leaving -= G[i].ports
meta.ports -= leaving
meta.rate -= group.rate
meta.groups.remove(group.id)
if len(meta.groups) == 0:
M_empty.add(meta.id)
for i in meta.ports - group.ports:
P[i].rate -= group.rate
for i in leaving:
P[i].rate -= meta.rate
P[i].meta.remove(meta.id)
group.groupRate[2] = 0
group.groupRate[3] = 0
for i in meta.groups:
G[i].groupRate[2] -= len(group.ports - meta.ports)*G[i].rate
G[i].groupRate[3] -= len(G[i].ports - group.ports)*group.rate
meta.metaRate[0] -= group.groupRate[0]
meta.metaRate[1] -= group.groupRate[1]
meta.metaRate[2] = len(meta.ports)*meta.rate - meta.metaRate[0]
def removeGain(group, meta, G):
leaving = group.ports.copy()
for i in meta.groups:
if i != group.id:
leaving -= G[i].ports
reduceRate = len(meta.ports)*meta.rate - group.groupRate[0] \
- len(meta.ports-leaving)*(meta.rate-group.rate)
return reduceRate
def reAggregate(meta, G, P, M, M_empty):
reduced = 0
leaving = -1
for i in meta.groups:
res = removeGain(G[i], meta, G)
if reduced <= res:
reduced = res
leaving = i
if reduced >= meta.metaRate[0]*0.1:
Remove(G[leaving], meta, P, G, M_empty)
Aggregate(G[leaving], M, G, P, M_empty, len(P))
def groupRate(group, meta, G):
effective = len(group.ports)*group.rate
duplicate = (len(group.ports)-1)*group.rate
extra_send = len(meta.ports-group.ports)*group.rate
extra_recv = 0
for i in meta.groups:
extra_recv += len(group.ports-G[i].ports)*G[i].rate
return [effective, duplicate, extra_send, extra_recv]
def metaRate(meta, G):
effective = 0
duplicate = 0
for i in meta.groups:
G[i].groupRate = groupRate(G[i], meta, G)
effective += G[i].groupRate[0]
duplicate += G[i].groupRate[1]
extra = len(meta.ports)*meta.rate - effective
return [effective, duplicate, extra]
def Diff(group, meta, G):
extraRate = len(meta.ports-group.ports)*group.rate + len(group.ports-meta.ports)*meta.rate
if extraRate < min(len(group.ports)*group.rate, meta.metaRate[0])/5:
diff = False
else:
diff = True
return diff
def Aggregate(group, M, G, P, M_empty, th_B):
if len(group.ports) >= th_B:
Assign(group, M[len(M)-1], P, G) #to the broadcast channel
elif len(group.ports) == 1:
Assign(group, M[list(group.ports)[0]], P, G) # to related unicast channel
else:
cost = 9e+100
index = -1
for i in set(range(1, len(M))) - M_empty:
aggrCost = AggregateCost(group, M[i], P)
if cost > aggrCost:
cost = aggrCost
index = i
if len(M_empty) > 0 and Diff(group, M[index], G):
Assign(group, M[M_empty.pop()], P, G)
else:
Assign(group, M[index], P, G)
# extra cost when a group is assigned to a meta-group
def AggregateCost(group, meta, P):
#extraCost = 0
#for i in meta.ports - group.ports:
# extraCost += linkCost(P[i].rate + group.rate) - linkCost(P[i].rate)
#for i in group.ports - meta.ports:
# extraCost += linkCost(P[i].rate + meta.rate) - linkCost(P[i].rate)
extraCost = len(meta.ports-group.ports)*group.rate + len(group.ports-meta.ports)*meta.rate
return extraCost
# a set of ports join a group
def Join(ports, group, meta, P, G):
if len(ports & group.ports) > 0:
error = 'group [%d] already has joining ports'%(group.id)
sys.exit(error)
for port_id in ports:
P[port_id].subscribe.add(group.id)
P[port_id].effective += group.rate
if port_id not in meta.ports:
P[port_id].meta.add(group.meta)
P[port_id].rate += meta.rate
group.groupRate[0] += len(ports)*group.rate
group.groupRate[1] += len(ports)*group.rate
group.groupRate[2] -= len(ports & meta.ports)*group.rate
for i in (meta.groups - set([group.id])):
G[i].groupRate[2] += len(ports-meta.ports)*G[i].rate
G[i].groupRate[3] -= len(ports & G[i].ports)*group.rate
group.groupRate[3] += len(ports-G[i].ports)*G[i].rate
group.ports.update(ports)
meta.ports.update(ports)
meta.metaRate[0] += len(ports)*group.rate
meta.metaRate[1] += len(ports)*group.rate
meta.metaRate[2] = len(meta.ports)*meta.rate - meta.metaRate[0]
# a set of ports leave a group
def Leave(ports, group, meta, P, G):
if (ports <= group.ports) == False:
error = 'group [%d] does not have leaving ports'%(group.id)
sys.exit(error)
for port_id in ports:
P[port_id].subscribe.discard(group.id)
P[port_id].effective -= group.rate
group.ports -= ports
leaving = ports.copy()
for group_id in meta.groups:
if group_id != group.id:
leaving -= G[group_id].ports
for port_id in leaving:
P[port_id].meta.remove(group.meta)
P[port_id].rate -= meta.rate
meta.ports -= leaving
group.groupRate[0] -= len(ports)*group.rate
group.groupRate[1] -= len(ports)*group.rate
group.groupRate[2] += len(ports & meta.ports)*group.rate
for i in (meta.groups - set([group.id])):
G[i].groupRate[2] -= len(ports-meta.ports)*G[i].rate
G[i].groupRate[3] += len(ports & G[i].ports)*group.rate
group.groupRate[3] -= len(ports-G[i].ports)*G[i].rate
meta.metaRate[0] -= len(ports)*group.rate
meta.metaRate[1] -= len(ports)*group.rate
meta.metaRate[2] = len(meta.ports)*meta.rate - meta.metaRate[0]
# total link cost for all ports
def TotalCost(P):
total = 0
effective = 0
for i in range(len(P)):
total += linkCost(P[i].rate)
effective += linkCost(P[i].effective)
return [total, effective]
def linkCost(r):
cost = r
#cost = r/float(10)+math.pow(2,r/float(1500))
return cost
def randomSample(ports, distribution):
N = len(ports)
size = 0
if distribution == 'uniform':
size = random.randint(1,N)
elif distribution == 'triangular':
size = int(random.triangular(0, N+3, 4))%N+1
elif distribution == 'beta':
size = int(N*random.betavariate(0.6, 0.6))+1
elif distribution == 'norm_r':
p = random.gauss(0.5,0.25)
if p < 0.5: p = abs(0.5-p)
else: p = abs(1.5-p)
size = int(N*p)%N+1
elif distribution == 'expo':
size = int(random.expovariate(0.12))%N+1
elif distribution == 'expo_r':
size = N-int(random.expovariate(0.12))%N
sample = set(sorted(random.sample(ports,size)))
return sample
def mean(array):
return sum(array)/float(len(array))
def median(array):
values = sorted(array)
if len(values) % 2 == 1:
return values[(len(values)+1)/2-1]
else:
lower = values[len(values)/2-1]
upper = values[len(values)/2]
return (float(lower + upper)) / 2
def printPort(port):
print '--------------------------------------------'
print 'port: ', port.id
print 'groups: ', sorted(list(port.subscribe))
print 'meta-groups:', sorted(list(port.meta))
print 'rate: ', port.rate
print 'effective: ', port.effective
def printGroup(group):
print '============================================'
print 'group: ', group.id
print 'ports: ', sorted(list(group.ports))
print 'rate: ', group.rate
print 'meta-group: ', group.meta
print 'groupRate: ', group.groupRate
def printMeta(meta):
print '++++++++++++++++++++++++++++++++++++++++++++'
print 'meta-group: ', meta.id
print 'ports: ', sorted(list(meta.ports))
print 'groups: ', sorted(list(meta.groups))
print 'rate: ', meta.rate
print 'metaRate: ', meta.metaRate
#!/usr/bin/python
import math
import random
mFile = open('dynamic_plot.m', 'w')
def mean(array):
return round(sum(array)/float(len(array)),3)
def median(array):
values = sorted(array)
if len(values) % 2 == 1:
return values[(len(values)+1)/2-1]
else:
lower = values[len(values)/2-1]
upper = values[len(values)/2]
return float((lower + upper)) / 2
Hosts = set()
for pod in range(8):
for edge in range(24):
for host in range(24):
hostname = '%d.%d.%d'%(pod,edge,host)
Hosts.add(hostname)
def computeDistribution(N_hosts, rounds):
podsN = []
edgesN = []
podsN_ = []
edgesN_ = []
for i in range(rounds):
if i%500 == 0:
print i
Pods = {}
Edges = {}
sample = random.sample(Hosts, N_hosts)
for hostname in sample:
ids = hostname.split('.')
pod = int(ids[0])
edge = int(ids[1])
host = int(ids[2])
edgename = '%d.%d'%(pod, edge)
if pod not in Pods.keys():
Pods[pod]=0
Pods[pod] += 1
if edgename not in Edges.keys():
Edges[edgename] = 0
Edges[edgename] += 1
podsN.append(len(Pods.keys()))
edgesN.append(len(Edges.keys()))
podn = 0
for pod in Pods.keys():
if Pods[pod] == 1:
podn += 1
podsN_.append(podn)
edgen = 0
for edge in Edges.keys():
if Edges[edge] == 1:
edgen += 1
edgesN_.append(edgen)
return [mean(podsN), mean(edgesN), mean(podsN_), mean(edgesN_)]
def computeUpdates(N, distribution):
p_join = 1/float(4608-N)
N_join = 1 + 3*(192-distribution[1])*24*p_join \
+ 9*(8-distribution[0])*576*p_join
p_leave = 1/float(N)
N_leave = 1 + 3*distribution[3]*p_leave + 9*distribution[2]*p_leave
N_burst = float(N + 3*distribution[1] + 9*distribution[0])/N
N_batch = float(distribution[1] + 3*distribution[0] + 9)/N
return [round(N_join,3), round(N_leave,3), round(N_burst,3), round(N_batch,3)]
sample = [10,20,30,40,60,80,100,120,150,200,250,300, \
350,400,500,600,700,800,900,1000]
distribution = []
updates = []
for N in sample:
print 'Number of hosts = %d'%N
dist = computeDistribution(N, 5000)
distribution.append(dist)
updates.append(computeUpdates(N, dist))
N_join = []
N_leave = []
N_burst = []
N_batch = []
for i in range(len(sample)):
print distribution[i]
N_join.append(updates[i][0])
N_leave.append(updates[i][1])
N_burst.append(updates[i][2])
N_batch.append(updates[i][3])
print N_join
print N_leave
print N_burst
print N_batch
mFile.write('size = '+str(sample)+';\n\n' \
+'N_join = '+str(N_join)+';\n\n' \
+'N_leave = '+str(N_leave)+';\n\n' \
+'N_burst = '+str(N_burst)+';\n\n' \
+'N_batch = '+str(N_batch)+';\n\n')
#!/usr/bin/python
import random
from network import *
import aggregate as aggr
#random.seed(0)
class AddressDistribution:
def __init__(self, k, n, r, pa, pb):
# core switches with l-th block
self.CoreSet = [0]*n
# aggregation switches with l-th block in type A pods
self.AggrSet_A = [0]*n
# aggregation switches with l-th block in type B pods
self.AggrSet_B = [0]*n
for i in range(n):
self.CoreSet[i] = set()
self.AggrSet_A[i] = set()
self.AggrSet_B[i] = set()
# block assigned to m-th core switch
self.Block_C = [0]*pow((k/2),2)
# blocks assigned to i-th aggregation switch in type A pods
self.BlockSet_A = [0]*(k/2)
# blocks assigned to i-th aggregation switch in type B pods
self.BlockSet_B = [0]*(k/2)
for i in range(k/2):
self.BlockSet_A[i] = set()
self.BlockSet_B[i] = set()
for l in range(n):
x = int(k*l/(2*n*pa))
y = l%(2*n*pa/k)
for i in range(x*pa, (x+1)*pa):
for j in range(y*pb, (y+1)*pb):
self.CoreSet[l].add(i*k/2+j)
for i in range(x*pa, (x+1)*pa):
self.AggrSet_A[l].add(i)
self.BlockSet_A[i].add(l)
y = l%(k/(2*pb))
for i in range(y*pb, (y+1)*pb):
self.AggrSet_B[l].add(i)
self.BlockSet_B[i].add(l)
for m in range(pow((k/2),2)):
self.Block_C[m] = int(int(2*m/k)/pa)*(2*n*pa/k) + int((m%(k/2))/pb)
class Group:
def __init__(self):
self.id = -1
self.block = -1
self.rate = -1
self.members = {}
self.hosts = []
self.tenant = -1
self.size = 0
class Groups:
def __init__(self, k, n, N, tenants, network):
self.blocks = [0]*n
for i in range(n):
self.blocks[i] = set()
tenantsList = []
for host in network.hosts['tenants'].keys():
tenantsList.extend(network.hosts['tenants'][host])
random.shuffle(tenantsList)
tenantsG = [0]*len(tenants)
self.groups = [0]*N
for i in range(N):
if i%1000 == 0:
print 'create group %d'%i
self.groups[i] = Group()
self.groups[i].id = i
self.groups[i].block = i%n
self.blocks[i%n].add(i)
self.groups[i].rate = random.randint(1,10)
#if i < len(tenants):
# self.groups[i].tenant = i
# sample = tenants[i]
#else:
self.groups[i].tenant = random.sample(tenantsList, 1)[0]
sample = randomSample(tenants[self.groups[i].tenant],'mix3',5)
tenantsG[self.groups[i].tenant] += 1
for hostname in sorted(sample):
IDs = hostname.strip('H').split('.')
pod_id = int(IDs[0])
edge_id = int(IDs[1])
host_id = int(IDs[2])
if pod_id not in self.groups[i].members.keys():
self.groups[i].members[pod_id] = {}
network.pods[pod_id].groups.add(i)
if edge_id not in self.groups[i].members[pod_id].keys():
self.groups[i].members[pod_id][edge_id] = set()
network.pods[pod_id].edges[edge_id].groups.add(i)
self.groups[i].members[pod_id][edge_id].add(host_id)
#network.hosts['groups'][hostname].add(i)
network.hosts['groups'][hostname] += 1
self.groups[i].hosts = sample
self.groups[i].size = len(sample)
#print tenantsG
def groupSize(self):
groupSize = {}
groupSize['pods'] = [0]*len(self.groups)
groupSize['edges'] = []
groupSize['members'] = [0]*len(self.groups)
for i in range(len(self.groups)):
groupSize['pods'][i] = len(self.groups[i].members.keys())
for pod in self.groups[i].members.keys():
groupSize['edges'].append(len(self.groups[i].members[pod].keys()))
groupSize['members'][i] = self.groups[i].size
return groupSize
def Dynamic(group, tenants, network, updates):
hosts_in = set(group.hosts)
hosts_out = set(tenants[group.tenant]) - hosts_in
join = True
leave = False
_min = 5
if len(hosts_out) == 0:
action = leave
elif len(hosts_in) == _min:
action = join
elif random.random() < 0.504:
action = join
else:
action = leave
if action == join:
hostname = random.sample(hosts_out, 1)[0]
else:
hostname = random.sample(hosts_in, 1)[0]
IDs = hostname.strip('H').split('.')
pod_id = int(IDs[0])
edge_id = int(IDs[1])
host_id = int(IDs[2])
if action == join:
if pod_id not in group.members.keys():
group.members[pod_id] = {}
updates['cores_J'] += 9 # needs to be changed!
if edge_id not in group.members[pod_id].keys():
group.members[pod_id][edge_id] = set()
updates['aggrs_J'] += 3 # needs to be changed!
group.members[pod_id][edge_id].add(host_id)
updates['edges_J'] += 1
#network.hosts['groups'][hostname].add(group.id)
network.hosts['groups'][hostname] += 1
group.hosts.add(hostname)
group.size += 1
if action == leave:
group.members[pod_id][edge_id].remove(host_id)
updates['edges_L'] += 1
if len(group.members[pod_id][edge_id]) == 0:
del group.members[pod_id][edge_id]
updates['aggrs_L'] += 3 # needs to be changed!
if(len(group.members[pod_id]) == 0):
del group.members[pod_id]
updates['cores_L'] += 9 # needs to be changed!
#network.hosts['groups'][hostname].remove(group.id)
network.hosts['groups'][hostname] -= 1
group.hosts.remove(hostname)
group.size -= 1
return group
def assignAggrGroups(G, network, distribution):
for i in range(len(G.groups)):
group = G.groups[i]
aggrFlag = 0
if len(group.members.keys()) > 1:
aggrFlag = 1
elif len(group.members.keys()) == 1:
if len(group.members[group.members.keys()[0]].keys()) > 1:
aggrFlag = 1
for pod in group.members.keys():
if aggrFlag == 1:
if pod%2 == 0:
for i in distribution.AggrSet_A[group.block]:
network.pods[pod].aggrs[i].groups.add(group.id)
else:
for i in distribution.AggrSet_B[group.block]:
network.pods[pod].aggrs[i].groups.add(group.id)
class multicastTree_simple:
def __init__(self, group, network, distribution, aggrGroupEdges):
self.id = group.id
self.rate = group.rate
if len(group.members.keys()) > 1:
self.layer = 3
for i in distribution.CoreSet[group.block]:
network.switches['C%s'%i] += 1
elif len(group.members.keys()) == 1:
if len(group.members[group.members.keys()[0]].keys()) > 1:
self.layer = 2
else:
self.layer = 1
core_id = random.sample(distribution.CoreSet[group.block],1)[0]
core_name = 'C%s'%core_id
for pod in group.members.keys():
if self.layer in [2,3]:
if pod%2 == 0:
for i in distribution.AggrSet_A[group.block]:
network.switches['A%s.%s'%(pod,i)] += 1
#network.pods[pod].aggrs[i].groups.add(group.id)
else:
for i in distribution.AggrSet_B[group.block]:
network.switches['A%s.%s'%(pod,i)] += 1
#network.pods[pod].aggrs[i].groups.add(group.id)
aggr_id = network.cores[core_id].down[pod]
aggr_name = 'A%s.%s'%(pod,aggr_id)
link = '%s-%s'%(core_name, aggr_name)
network.links[link] += self.rate * (self.layer==3)
for edge in group.members[pod].keys():
edge_name = 'E%s.%s'%(pod,edge)
network.switches[edge_name] += 1
link = '%s-%s'%(aggr_name, edge_name)
network.links[link] += self.rate * (self.layer in [2,3])
for host in group.members[pod][edge]:
host_name = 'H%s.%s.%s'%(pod,edge,host)
link = '%s-%s'%(edge_name, host_name)
network.links[link] += self.rate
if len(aggrGroupEdges) > 0:
for edge in aggrGroupEdges[group.id][pod]:
edge_name = 'E%s.%s'%(pod,edge)
link = '%s-%s'%(aggr_name, edge_name)
network.aggrlinks[link] += self.rate
def GenerateTrees(N, G, network, distribution, aggrGroupEdges):
Trees = [0]*N
for i in range(N):
if i%1000 == 0:
print 'create tree %d'%i
Trees[i] = multicastTree_simple(G.groups[i], network, distribution, aggrGroupEdges)
return Trees
def edgeAggregate(portNum, metaNum, pod_id, edge_id, network, G):
P = [0]*portNum
for i in range(portNum):
P[i] = aggr.Port(i)
M = [0]*metaNum
for i in range(metaNum):
M[i] = aggr.MetaGroup(i)
groups = network.pods[pod_id].edges[edge_id].groups
Gr = [0]*len(groups)
i = 0
for g_id in groups:
ports = G.groups[g_id].members[pod_id][edge_id]
Gr[i] = aggr.Group(i, g_id, ports, G.groups[g_id].rate, P)
i += 1
G_unassigned = set(range(len(groups)))
M_empty = set(range(portNum, metaNum-1))
while len(G_unassigned) > 0:
aggr.Aggregate(Gr[G_unassigned.pop()], M, Gr, P, M_empty, portNum)
linkRate = [0]*2
linkRate[0] = []
linkRate[1] = []
for i in range(portNum):
linkRate[0].append(P[i].effective)
linkRate[1].append(P[i].rate)
switchAddr = [0]*2
switchAddr[0] = len(groups)
for i in range(metaNum):
if len(M[i].ports) > 0:
switchAddr[1] += 1
return [linkRate, switchAddr]
def aggregateEdges(k, G, network, C):
linkRate = [[],[]]
switchAddr = [[],[]]
for pod_id in range(k):
print '-------------------------pod %d'%pod_id
for edge_id in range(k/2):
print 'edge %d'%edge_id
res = edgeAggregate(k/2, C, pod_id, edge_id, network, G)
linkRate[0].extend(res[0][0])
linkRate[1].extend(res[0][1])
switchAddr[0].append(res[1][0])
switchAddr[1].append(res[1][1])
aggrFile = open('plot/output/aggregateEdges.py', 'w')
aggrFile.write('links = '+ str(linkRate)+'\n\n' + 'switches = '+str(switchAddr))
return [linkRate, switchAddr]
def aggrAggregate(portNum, metaNum, pod_id, aggr_id, network, G, aggrGroupEdges):
P = [0]*portNum
for i in range(portNum):
P[i] = aggr.Port(i)
M = [0]*metaNum
for i in range(metaNum):
M[i] = aggr.MetaGroup(i)
idmap = {}
groups = network.pods[pod_id].aggrs[aggr_id].groups
Gr = [0]*len(groups)
i = 0
for g_id in groups:
ports = set(G.groups[g_id].members[pod_id].keys())
Gr[i] = aggr.Group(i, g_id, ports, G.groups[g_id].rate, P)
idmap[g_id] = i
i += 1
G_unassigned = set(range(len(groups)))
M_empty = set(range(portNum, metaNum-1))
while len(G_unassigned) > 0:
aggr.Aggregate(Gr[G_unassigned.pop()], M, Gr, P, M_empty, portNum)
for g_id in groups:
if g_id not in aggrGroupEdges.keys():
aggrGroupEdges[g_id] = {}
aggrGroupEdges[g_id][pod_id] = M[Gr[idmap[g_id]].meta].ports
switchAddr = 0
for i in range(metaNum):
if len(M[i].ports)>0:
switchAddr += 1
return switchAddr
def aggregatePods(k, G, network, pa, pb, C):
aggrGroupEdges = {}
for pod_id in range(k):
print '-------------------------pod %d'%pod_id
if pod_id%2 == 0:
for aggr_id in range(0,k/2,pa):
print 'aggr %d'%aggr_id
addrNum = aggrAggregate(k/2, C, pod_id, aggr_id, network, G, aggrGroupEdges)
for i in range(aggr_id, aggr_id+pa):
network.aggrs['A%s.%s'%(pod_id, i)] = addrNum
else:
for aggr_id in range(0,k/2,pb):
print 'aggr %d'%aggr_id
addrNum = aggrAggregate(k/2, C, pod_id, aggr_id, network, G, aggrGroupEdges)
for i in range(aggr_id, aggr_id+pb):
network.aggrs['A%s.%s'%(pod_id, i)] = addrNum
return aggrGroupEdges
def doAggregate(k, G, network, distribution, C, pa, pb, layer):
aggrGroupEdges = {}
if layer == 'a': # aggregate on aggreation layer
assignAggrGroups(G, network, distribution)
aggrGroupEdges = aggregatePods(k, G, network, pa, pb, C)
elif layer == 'e': # aggregate on edge layer
aggregateEdges(k, G, network, C)
return aggrGroupEdges
def PrintAggregate(args, P, G, M):
if 'group' in args or 'g' in args:
for i in range(len(G)):
aggr.printGroup(G[i])
print ''
if 'meta' in args or 'm' in args:
for i in range(len(M)):
aggr.printMeta(M[i])
print ''
if 'port' in args or 'p' in args:
for i in range(len(P)):
aggr.printPort(P[i])
print ''
if 'stat' in args or 's' in args:
totalCost = aggr.TotalCost(P)
print 'total cost: ', totalCost[0]
print 'effective cost: ', totalCost[1]
effective = 0
extra = 0
duplicate = 0
total = 0
for i in range(len(M)):
effective += M[i].metaRate[0]
duplicate += M[i].metaRate[1]
extra += M[i].metaRate[2]
print 'meta rate: ', [effective, duplicate, extra, extra/float(duplicate)]
'''
extra_send = []
extra_recv = []
for i in range(len(G)):
extra_send.append(G[i].groupRate[2])
extra_recv.append(G[i].groupRate[3])
print 'group extra_send [min, max, mean, median]: ',[min(extra_send), max(extra_send), \
mean(extra_send), median(extra_send)]
print 'group extra_recv [min, max, mean, median]: ',[min(extra_recv), max(extra_recv), \
mean(extra_recv), median(extra_recv)]
'''
def randomSample(population, method, _min):
N = len(population)
size = 0
if method == 'tri': # triangular distribution
size = int(random.triangular(_min-1, N+3, _min+4))%N+1
elif method == 'beta': # beta distribution
size = int((N-_min+1)*random.betavariate(0.6, 0.6))+_min
elif method == 'norm_r': # reverse norm distribution
p = random.gauss(0.5,0.25)
if p < 0.5: p = abs(0.5-p)
else: p = abs(1.5-p)
size = int(N*p)%N+1
elif method == 'expo': # exponential distribution
size = int(random.expovariate(0.12))%N+1
elif method == 'expo_r': # reverse exponential distribution
size = N-int(random.expovariate(0.12))%N
elif method == 'gamma': # gamma distribution
size = int(random.gammavariate(2.5,2)*N/15+_min-1)%N+1
elif method == 'gamma': # gamma distribution
size = int(random.gammavariate(2.5,2)*N/15+_min-1)%N+1
elif method == 'mix1':
seed = random.random()
if seed < 0.1:
size = random.randint(_min,N)
else:
size = int(random.gammavariate(2.5,0.5)*N/15+_min-1)%N+1
elif method == 'mix2':
r = random.random()
if r < 0.02:
size = N-int(random.gammavariate(1,0.1)*N/15)%N
else:
size = int(random.gammavariate(1.9,0.16)*N/15+_min-1)%N+1
elif method == 'mix3':
r = random.random()
if r < 0.02:
size = N-int(random.gammavariate(1,0.1)*N/15)%N
else:
size = int(random.gammavariate(2,0.2)*N/15+_min-1)%N+1
elif method == 'mix4':
r = random.random()
if r < 0.02:
size = N-int(random.gammavariate(1,0.1)*N/15)%N
elif r >= 0.02 and r < 0.52:
size = random.randint(_min, N)
else:
size = int(random.gammavariate(2,0.2)*N/15+_min-1)%N+1
else: # uniform distribution
size = random.randint(_min,N)
size = max(size, _min)
sample = set(sorted(random.sample(population,size)))
return sample
#!/usr/bin/python
import random
random.seed(0)
class Switch:
def __init__(self, k, layer, ID):
self.k = k
self.layer = layer
self.groups = set()
if layer == 1: # edge switch
self.up = range(k/2)
self.down = range(k/2)
self.name = 'E%d.%d'%(ID[0],ID[1])
elif layer == 2: # aggregation switch
self.up = [-1]*(k/2)
self.down = range(k/2)
self.name = 'A%d.%d'%(ID[0],ID[1])
elif layer == 3: # core switch
self.up = -1
self.down = [-1]*k
self.name = 'C%d'%ID
else:
self.up = -1
self.down = -1
class Pod:
def __init__(self, k, pod_id):
self.k = k
self.id = pod_id
self.type = ''
self.groups = set()
self.edges = [0]*(k/2)
for i in range(k/2):
self.edges[i] = Switch(k, 1, [pod_id, i])
self.aggrs = [0]*(k/2)
for i in range(k/2):
self.aggrs[i] = Switch(k, 2, [pod_id, i])
class ABFatTree:
def __init__(self, k):
self.k = k
self.links = {}
self.switches = {}
self.hosts = {}
self.hosts['tenants'] = {}
self.hosts['groups'] = {}
self.aggrs = {}
self.aggrlinks = {}
self.cores = [0]*pow((k/2),2)
for i in range(pow((k/2),2)):
self.cores[i] = Switch(k, 3, i)
self.switches[self.cores[i].name] = 0
self.pods = [0]*k
for i in range(k):
#print 'create pod %d'%i
self.pods[i] = Pod(k, i)
if i%2 == 0:
self.pods[i].type = 'A'
for j in range(k/2):
for h in range(k/2):
self.pods[i].aggrs[j].up[h] = j*k/2+h
self.cores[j*k/2+h].down[i] = j
link = '%s-A%s.%s'%(self.cores[j*k/2+h].name,i,j)
self.links[link] = 0
elif i%2 == 1:
self.pods[i].type = 'B'
for j in range(k/2):
for h in range(k/2):
self.pods[i].aggrs[j].up[h] = j+h*k/2
self.cores[j+h*k/2].down[i] = j
link = '%s-A%s.%s'%(self.cores[j+h*k/2].name,i,j)
self.links[link]= 0
for p in range(k):
for a in range(k/2):
self.switches[self.pods[p].aggrs[a].name] = 0
self.aggrs[self.pods[p].aggrs[a].name] = 0 # for aggr switches aggregation
for e in range(k/2):
link = 'A%d.%d-E%d.%d'%(p,a, p,e)
self.links[link] = 0
self.aggrlinks[link] = 0 # for aggr switches aggregation
for e in range(k/2):
self.switches[self.pods[p].edges[e].name] = 0
for h in range(k/2):
link = 'E%d.%d-H%d.%d.%d'%(p,e, p,e,h)
self.links[link] = 0
host = 'H%d.%d.%d'%(p,e,h)
self.hosts['tenants'][host] = set()
#self.hosts['groups'][host] = set()
self.hosts['groups'][host] = 0
def Tenants(network, TN, _min, _max, mode):
C = 8
tenants = []
hosts_avaliable = set(network.hosts['tenants'].keys())
hosts_in_pods = Hosts_in_Pods(hosts_avaliable)
for i in range(TN):
r = random.random()
if r < 0.02:
size = random.randint(_min, _max)
else:
size = int((random.expovariate(2)/10)*(_max-_min))%(_max-_min)+_min
tenant = []
if mode in ['random', 'r']:
tenant = random.sample(hosts_avaliable, size)
for host in tenant:
network.hosts['tenants'][host].add(i)
if len(network.hosts['tenants'][host]) >= C:
hosts_avaliable.remove(host)
elif mode in ['collocate', 'c']:
usedPods = set()
while len(tenant) < size:
pod_id = random.sample(set(hosts_in_pods.keys())-usedPods, 1)[0]
usedPods.add(pod_id)
if size-len(tenant) < len(hosts_in_pods[pod_id]):
tenant.extend(Sample_in_Pod(hosts_in_pods[pod_id], size-len(tenant)))
else:
tenant.extend(list(hosts_in_pods[pod_id]))
for host in tenant:
network.hosts['tenants'][host].add(i)
if len(network.hosts['tenants'][host]) >= C:
pod_id = int(host.strip('H').split('.')[0])
hosts_in_pods[pod_id].remove(host)
if len(hosts_in_pods[pod_id]) == 0:
del hosts_in_pods[pod_id]
tenants.append(sorted(tenant))
return tenants
def Tenants_(network, TN, _min, _max, mode):
C = 20
tenants = []
tenantSize = []
hosts_avaliable = set(network.hosts['tenants'].keys())
hosts_in_pods = Hosts_in_Pods(hosts_avaliable)
space_in_pods = Space_in_Pods(hosts_in_pods)
#print space_in_pods
for i in range(TN):
r = random.random()
if r < 0.02:
size = random.randint(_min, _max)
else:
size = int((random.expovariate(4)/10)*(_max-_min))%(_max-_min)+_min
#print size
tenantSize.append(size)
#tenantSize = sorted(tenantSize)
for i in range(TN):
size = tenantSize.pop()
#print size
tenant = []
if mode in ['random', 'r']:
tenant = random.sample(hosts_avaliable, size)
for host in tenant:
network.hosts['tenants'][host].add(i)
if len(network.hosts['tenants'][host]) >= C:
hosts_avaliable.remove(host)
elif mode in ['collocate', 'c']:
sorted_pods = sorted(space_in_pods.items(), key=lambda x: x[1])
#print sorted_pods
#usedPods = set()
while len(tenant) < size:
pod_id = sorted_pods.pop()[0]
#pod_id = random.sample(set(hosts_in_pods.keys())-usedPods, 1)[0]
#usedPods.add(pod_id)
if size-len(tenant) < len(hosts_in_pods[pod_id]):
tenant.extend(Sample_in_Pod(hosts_in_pods[pod_id], size-len(tenant)))
else:
tenant.extend(list(hosts_in_pods[pod_id]))
for host in tenant:
network.hosts['tenants'][host].add(i)
if len(network.hosts['tenants'][host]) >= C:
pod_id = int(host.strip('H').split('.')[0])
hosts_in_pods[pod_id].remove(host)
space_in_pods[pod_id] -= 1
if len(hosts_in_pods[pod_id]) == 0:
del hosts_in_pods[pod_id]
del space_in_pods[pod_id]
tenants.append(sorted(tenant))
print space_in_pods
return tenants
def Sample_in_Pod(hosts_in_pod, size):
hosts = []
usedEdges = set()
hosts_in_edges = Hosts_in_Edges(hosts_in_pod)
while len(hosts) < size:
edge_id = random.sample(set(hosts_in_edges.keys())-usedEdges, 1)[0]
usedEdges.add(edge_id)
if size-len(hosts) < len(hosts_in_edges[edge_id]):
hosts.extend(random.sample(hosts_in_edges[edge_id], size-len(hosts)))
else:
hosts.extend(list(hosts_in_edges[edge_id]))
return hosts
def Hosts_in_Pods(hosts):
hosts_in_pods = {}
for host in hosts:
pod_id = int(host.strip('H').split('.')[0])
if pod_id not in hosts_in_pods.keys():
hosts_in_pods[pod_id] = set()
hosts_in_pods[pod_id].add(host)
return hosts_in_pods
def Space_in_Pods(hosts_in_pods):
space_in_pods = {}
for pod_id in hosts_in_pods.keys():
space_in_pods[pod_id] = len(hosts_in_pods[pod_id])
return space_in_pods
def Hosts_in_Edges(hosts_in_pod):
hosts_in_edges = {}
for host in hosts_in_pod:
edge_id = int(host.strip('H').split('.')[1])
if edge_id not in hosts_in_edges.keys():
hosts_in_edges[edge_id] = set()
hosts_in_edges[edge_id].add(host)
return hosts_in_edges
def Tenants_x(network, _min, _max, mode):
tenants = []
hosts_avaliable = set(network.hosts['tenants'].keys())
hosts_in_pods = Hosts_in_Pods(hosts_avaliable)
i = 0
while len(hosts_avaliable) > _max:
size = int((random.expovariate(2)/5)*(_max-_min))%(_max-_min)+_min
tenant = []
if mode in ['collocate', 'c']:
usedPods = set()
while len(tenant) < size:
pod_id = random.sample(set(hosts_in_pods.keys())-usedPods, 1)[0]
usedPods.add(pod_id)
if size-len(tenant) < len(hosts_in_pods[pod_id]):
tenant.extend(Sample_in_Pod(hosts_in_pods[pod_id], size-len(tenant)))
else:
tenant.extend(list(hosts_in_pods[pod_id]))
for host in tenant:
network.hosts['tenants'][host].add(i)
pod_id = int(host.strip('H').split('.')[0])
hosts_in_pods[pod_id].remove(host)
if len(hosts_in_pods[pod_id]) == 0:
del hosts_in_pods[pod_id]
elif mode in ['random', 'r']:
tenant = sorted(random.sample(hosts_avaliable,size))
for host in tenant:
network.hosts['tenants'][host].add(i)
hosts_avaliable -= set(tenant)
tenants.append(sorted(tenant))
i += 1
for host in hosts_avaliable:
network.hosts['tenants'][host].add(i)
tenants.append(sorted(list(hosts_avaliable)))
return tenants
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Polygon
# Generate some data from five different probability distributions,
# each with different characteristics. We want to play with how an IID
# bootstrap resample of the data preserves the distributional
# properties of the original sample, and a boxplot is one visual tool
# to make this assessment
numDists = 5
randomDists = ['Normal(1,1)',' Lognormal(1,1)', 'Exp(1)', 'Gumbel(6,4)',
'Triangular(2,9,11)']
N = 500
norm = np.random.normal(1,1, N)
logn = np.random.lognormal(1,1, N)
expo = np.random.exponential(1, N)
gumb = np.random.gumbel(6, 4, N)
tria = np.random.triangular(2, 9, 11, N)
# Generate some random indices that we'll use to resample the original data
# arrays. For code brevity, just use the same random indices for each array
bootstrapIndices = np.random.random_integers(0, N-1, N)
normBoot = norm[bootstrapIndices]
expoBoot = expo[bootstrapIndices]
gumbBoot = gumb[bootstrapIndices]
lognBoot = logn[bootstrapIndices]
triaBoot = tria[bootstrapIndices]
data = [norm, normBoot, logn, lognBoot, expo, expoBoot, gumb, gumbBoot,
tria, triaBoot]
fig = plt.figure(figsize=(10,6))
fig.canvas.set_window_title('A Boxplot Example')
ax1 = fig.add_subplot(111)
plt.subplots_adjust(left=0.075, right=0.95, top=0.9, bottom=0.25)
bp = plt.boxplot(data, notch=0, sym='+', vert=1, whis=1.5)
plt.setp(bp['boxes'], color='black')
plt.setp(bp['whiskers'], color='black')
plt.setp(bp['fliers'], color='red', marker='+')
# Add a horizontal grid to the plot, but make it very light in color
# so we can use it for reading data values but not be distracting
ax1.yaxis.grid(True, linestyle='-', which='major', color='lightgrey',
alpha=0.5)
# Hide these grid behind plot objects
ax1.set_axisbelow(True)
ax1.set_title('Comparison of IID Bootstrap Resampling Across Five Distributions')
ax1.set_xlabel('Distribution')
ax1.set_ylabel('Value')
# Now fill the boxes with desired colors
boxColors = ['darkkhaki','royalblue']
numBoxes = numDists*2
medians = range(numBoxes)
for i in range(numBoxes):
box = bp['boxes'][i]
boxX = []
boxY = []
for j in range(5):
boxX.append(box.get_xdata()[j])
boxY.append(box.get_ydata()[j])
boxCoords = zip(boxX,boxY)
# Alternate between Dark Khaki and Royal Blue
k = i % 2
boxPolygon = Polygon(boxCoords, facecolor=boxColors[k])
ax1.add_patch(boxPolygon)
# Now draw the median lines back over what we just filled in
med = bp['medians'][i]
medianX = []
medianY = []
for j in range(2):
medianX.append(med.get_xdata()[j])
medianY.append(med.get_ydata()[j])
plt.plot(medianX, medianY, 'k')
medians[i] = medianY[0]
# Finally, overplot the sample averages, with horixzontal alignment
# in the center of each box
plt.plot([np.average(med.get_xdata())], [np.average(data[i])],
color='w', marker='*', markeredgecolor='k')
# Set the axes ranges and axes labels
ax1.set_xlim(0.5, numBoxes+0.5)
top = 40
bottom = -5
ax1.set_ylim(bottom, top)
xtickNames = plt.setp(ax1, xticklabels=np.repeat(randomDists, 2))
plt.setp(xtickNames, rotation=45, fontsize=8)
# Due to the Y-axis scale being different across samples, it can be
# hard to compare differences in medians across the samples. Add upper
# X-axis tick labels with the sample medians to aid in comparison
# (just use two decimal places of precision)
pos = np.arange(numBoxes)+1
upperLabels = [str(np.round(s, 2)) for s in medians]
weights = ['bold', 'semibold']
for tick,label in zip(range(numBoxes),ax1.get_xticklabels()):
k = tick % 2
ax1.text(pos[tick], top-(top*0.05), upperLabels[tick],
horizontalalignment='center', size='x-small', weight=weights[k],
color=boxColors[k])
# Finally, add a basic legend
plt.figtext(0.80, 0.08, str(N) + ' Random Numbers' ,
backgroundcolor=boxColors[0], color='black', weight='roman',
size='x-small')
plt.figtext(0.80, 0.045, 'IID Bootstrap Resample',
backgroundcolor=boxColors[1],
color='white', weight='roman', size='x-small')
plt.figtext(0.80, 0.015, '*', color='white', backgroundcolor='silver',
weight='roman', size='medium')
plt.figtext(0.815, 0.013, ' Average Value', color='black', weight='roman',
size='x-small')
plt.show()
size = [10, 20, 30, 40, 60, 80, 100, 120, 150, 200, 250, 300, 350, 400, 500, 600, 700, 800, 900, 1000];
N_join = [6.204, 4.343, 3.734, 3.499, 3.222, 3.004, 2.809, 2.631, 2.399, 2.078, 1.828, 1.635, 1.485, 1.37, 1.213, 1.12, 1.067, 1.037, 1.02, 1.011];
N_leave = [6.602, 4.435, 3.772, 3.514, 3.227, 3.012, 2.818, 2.645, 2.405, 2.083, 1.835, 1.64, 1.488, 1.372, 1.214, 1.121, 1.067, 1.037, 1.02, 1.011];
N_burst = [9.255, 7.212, 6.15, 5.515, 4.793, 4.375, 4.083, 3.859, 3.587, 3.25, 2.991, 2.78, 2.605, 2.458, 2.223, 2.047, 1.91, 1.803, 1.717, 1.646];
N_batch = [3.652, 2.521, 2.017, 1.73, 1.414, 1.238, 1.118, 1.028, 0.922, 0.795, 0.7, 0.623, 0.561, 0.508, 0.426, 0.364, 0.316, 0.279, 0.249, 0.224];
#!/usr/bin/python
import matplotlib.pyplot as plt
plt.rc('pdf',fonttype = 42)
plt.rc('ps',fonttype = 42)
size = [10, 20, 30, 40, 60, 80, 100, 120, 150, 200, 250, 300, 350, 400, 500, 600, 700, 800, 900, 1000];
N_join = [6.204, 4.343, 3.734, 3.499, 3.222, 3.004, 2.809, 2.631, 2.399, 2.078, \
1.828, 1.635, 1.485, 1.37, 1.213, 1.12, 1.067, 1.037, 1.02, 1.011];
N_leave = [6.602, 4.435, 3.772, 3.514, 3.227, 3.012, 2.818, 2.645, 2.405, 2.083, \
1.835, 1.64, 1.488, 1.372, 1.214, 1.121, 1.067, 1.037, 1.02, 1.011];
N_burst = [9.255, 7.212, 6.15, 5.515, 4.793, 4.375, 4.083, 3.859, 3.587, 3.25, \
2.991, 2.78, 2.605, 2.458, 2.223, 2.047, 1.91, 1.803, 1.717, 1.646];
N_batch = [3.652, 2.521, 2.017, 1.73, 1.414, 1.238, 1.118, 1.028, 0.922, 0.795, \
0.7, 0.623, 0.561, 0.508, 0.426, 0.364, 0.316, 0.279, 0.249, 0.224];
plt.figure(1)
ax1 = plt.subplot(111)
p1, = plt.plot(size, N_join, 'o', color='blue')
p1.set_markeredgecolor('blue')
p1.set_markerfacecolor('white')
p2, = plt.plot(size, N_leave, 'x', color='red')
p3, = plt.plot(size, N_burst, '+', color='black')
p4, = plt.plot(size, N_batch, '*', color='green')
p4.set_markeredgecolor('green')
label1 = 'Next join when group size is $N$'
label2 = 'Next leave when group size is $N$'
label3 = '$N$ burst joins, w/o batch operation'
label4 = '$N$ burst joins, with batch operation'
l = plt.legend([p1,p2,p3,p4], [label1, label2, label3, label4], \
bbox_to_anchor=(1,1), loc=1, prop={'size':9}, numpoints=1, markerscale=0.8)
l.set_frame_on(False)
ax1.yaxis.grid(True, linestyle='-', which='major', color='lightgrey')
plt.yticks(range(0,11))
plt.xlabel('$(N)$ Number of hosts that subscribe to the group',fontsize=11)
plt.ylabel('Number of updates per event', fontsize=11)
plt.xlim(-50,1050)
plt.tick_params(labelsize=11)
plt.show()
File added
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
File added
This diff is collapsed.
This diff is collapsed.
File added
File added
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment