Merge branch 'addDiagnostics' into develop

This commit is contained in:
Leonardo Bautista-Gomez 2023-04-13 13:39:33 +02:00
commit d51cefabb7
4 changed files with 56 additions and 8 deletions

View File

@ -32,7 +32,7 @@ class Result:
"""Generic function to add a metric to the results.""" """Generic function to add a metric to the results."""
self.metrics[name] = metric self.metrics[name] = metric
def dump(self, execID): def dump(self):
"""It dumps the results of the simulation in an XML file.""" """It dumps the results of the simulation in an XML file."""
if not os.path.exists("results"): if not os.path.exists("results"):
os.makedirs("results") os.makedirs("results")

View File

@ -25,6 +25,7 @@ class Simulator:
self.logLevel = config.logLevel self.logLevel = config.logLevel
self.proposerID = 0 self.proposerID = 0
self.glob = [] self.glob = []
self.execID = execID
# In GossipSub the initiator might push messages without participating in the mesh. # In GossipSub the initiator might push messages without participating in the mesh.
# proposerPublishOnly regulates this behavior. If set to true, the proposer is not # proposerPublishOnly regulates this behavior. If set to true, the proposer is not
@ -53,6 +54,13 @@ class Simulator:
offset = heavyVal*self.shape.chi offset = heavyVal*self.shape.chi
random.shuffle(rows) random.shuffle(rows)
random.shuffle(columns) random.shuffle(columns)
self.logger.debug("There is a total of %d validators" % totalValidators, extra=self.format)
self.logger.debug("Shuffling a total of %d rows/columns" % len(rows), extra=self.format)
self.logger.debug("Shuffled rows: %s" % str(rows), extra=self.format)
self.logger.debug("Shuffled columns: %s" % str(columns), extra=self.format)
assignedRows = []
assignedCols = []
for i in range(self.shape.numberNodes): for i in range(self.shape.numberNodes):
if self.config.evenLineDistribution: if self.config.evenLineDistribution:
if i < int(heavyVal/self.shape.vpn2): # First start with the heavy nodes if i < int(heavyVal/self.shape.vpn2): # First start with the heavy nodes
@ -65,6 +73,11 @@ class Simulator:
r = set(rows[start:end]) r = set(rows[start:end])
c = set(columns[start:end]) c = set(columns[start:end])
val = Validator(i, int(not i!=0), self.logger, self.shape, r, c) val = Validator(i, int(not i!=0), self.logger, self.shape, r, c)
self.logger.debug("Validators %d row IDs: %s" % (val.ID, val.rowIDs), extra=self.format)
self.logger.debug("Validators %d column IDs: %s" % (val.ID, val.columnIDs), extra=self.format)
assignedRows = assignedRows + list(r)
assignedCols = assignedCols + list(c)
else: else:
val = Validator(i, int(not i!=0), self.logger, self.shape) val = Validator(i, int(not i!=0), self.logger, self.shape)
if i == self.proposerID: if i == self.proposerID:
@ -72,6 +85,11 @@ class Simulator:
else: else:
val.logIDs() val.logIDs()
self.validators.append(val) self.validators.append(val)
assignedRows.sort()
assignedCols.sort()
self.logger.debug("Rows assigned: %s" % str(assignedRows), extra=self.format)
self.logger.debug("Columns assigned: %s" % str(assignedCols), extra=self.format)
self.logger.debug("Validators initialized.", extra=self.format) self.logger.debug("Validators initialized.", extra=self.format)
def initNetwork(self): def initNetwork(self):
@ -86,12 +104,14 @@ class Simulator:
columnChannels[id].append(v) columnChannels[id].append(v)
# Check rows/columns distribution # Check rows/columns distribution
#totalR = 0 distR = []
#totalC = 0 distC = []
#for r in rowChannels: for r in rowChannels:
# totalR += len(r) distR.append(len(r))
#for c in columnChannels: for c in columnChannels:
# totalC += len(c) distC.append(len(c))
self.logger.debug("Number of validators per row; Min: %d, Max: %d" % (min(distR), max(distR)), extra=self.format)
self.logger.debug("Number of validators per column; Min: %d, Max: %d" % (min(distC), max(distC)), extra=self.format)
for id in range(self.shape.blockSize): for id in range(self.shape.blockSize):
@ -164,6 +184,29 @@ class Simulator:
logger.addHandler(ch) logger.addHandler(ch)
self.logger = logger self.logger = logger
def printDiagnostics(self):
"""Print all required diagnostics to check when a block does not become available"""
for val in self.validators:
(a, e) = val.checkStatus()
if e-a > 0 and val.ID != 0:
self.logger.warning("Node %d is missing %d samples" % (val.ID, e-a), extra=self.format)
for r in val.rowIDs:
row = val.getRow(r)
if row.count() < len(row):
self.logger.debug("Row %d: %s" % (r, str(row)), extra=self.format)
neiR = val.rowNeighbors[r]
for nr in neiR:
self.logger.debug("Row %d, Neighbor %d sent: %s" % (r, val.rowNeighbors[r][nr].node.ID, val.rowNeighbors[r][nr].received), extra=self.format)
self.logger.debug("Row %d, Neighbor %d has: %s" % (r, val.rowNeighbors[r][nr].node.ID, self.validators[val.rowNeighbors[r][nr].node.ID].getRow(r)), extra=self.format)
for c in val.columnIDs:
col = val.getColumn(c)
if col.count() < len(col):
self.logger.debug("Column %d: %s" % (c, str(col)), extra=self.format)
neiC = val.columnNeighbors[c]
for nc in neiC:
self.logger.debug("Column %d, Neighbor %d sent: %s" % (c, val.columnNeighbors[c][nc].node.ID, val.columnNeighbors[c][nc].received), extra=self.format)
self.logger.debug("Column %d, Neighbor %d has: %s" % (c, val.columnNeighbors[c][nc].node.ID, self.validators[val.columnNeighbors[c][nc].node.ID].getColumn(c)), extra=self.format)
def run(self): def run(self):
"""It runs the main simulation until the block is available or it gets stucked.""" """It runs the main simulation until the block is available or it gets stucked."""
self.glob.checkRowsColumns(self.validators) self.glob.checkRowsColumns(self.validators)
@ -232,6 +275,8 @@ class Simulator:
if len(missingVector) > self.config.steps4StopCondition: if len(missingVector) > self.config.steps4StopCondition:
if missingSamples == missingVector[-self.config.steps4StopCondition]: if missingSamples == missingVector[-self.config.steps4StopCondition]:
self.logger.debug("The block cannot be recovered, failure rate %d!" % self.shape.failureRate, extra=self.format) self.logger.debug("The block cannot be recovered, failure rate %d!" % self.shape.failureRate, extra=self.format)
if self.config.diagnostics:
self.printDiagnostics()
break break
missingVector.append(missingSamples) missingVector.append(missingSamples)
elif missingSamples == 0: elif missingSamples == 0:

View File

@ -76,6 +76,9 @@ randomSeed = "DAS"
# Number of steps without progress to stop simulation # Number of steps without progress to stop simulation
steps4StopCondition = 7 steps4StopCondition = 7
# If True, print diagnostics when the block is not available
diagnostics = False
def nextShape(): def nextShape():
for run, fr, class1ratio, chi, vpn1, vpn2, blockSize, nn, netDegree, bwUplinkProd, bwUplink1, bwUplink2 in itertools.product( for run, fr, class1ratio, chi, vpn1, vpn2, blockSize, nn, netDegree, bwUplinkProd, bwUplink1, bwUplink2 in itertools.product(
runs, failureRates, class1ratios, chis, validatorsPerNode1, validatorsPerNode2, blockSizes, numberNodes, netDegrees, bwUplinksProd, bwUplinks1, bwUplinks2): runs, failureRates, class1ratios, chis, validatorsPerNode1, validatorsPerNode2, blockSizes, numberNodes, netDegrees, bwUplinksProd, bwUplinks1, bwUplinks2):

View File

@ -36,7 +36,7 @@ def runOnce(config, shape, execID):
sim.logger.info("Shape: %s ... Block Available: %d in %d steps" % (str(sim.shape.__dict__), result.blockAvailable, len(result.missingVector)), extra=sim.format) sim.logger.info("Shape: %s ... Block Available: %d in %d steps" % (str(sim.shape.__dict__), result.blockAvailable, len(result.missingVector)), extra=sim.format)
if config.dumpXML: if config.dumpXML:
result.dump(execID) result.dump()
return result return result