def __init__(self, offsets, data_segments, partition, pwidth, pheight, \ connections=None): self.wid = StencilWorker._id self.offsets = offsets self.data_segments = data_segments self.partition = partition self.col, self.row = 0, 0 self.width, self.height = self.partition.cols, self.partition.rows self.pwidth, self.pheight = pwidth, pheight self.conns = connections if rank == 0: log.debug("Worker %d has %s" % (StencilWorker._id, self.partition)) StencilWorker._id += 1 else: self.comm = Communicator(self)
class StencilWorker(object): _id = 0 def __init__(self, offsets, data_segments, partition, pwidth, pheight, \ connections=None): self.wid = StencilWorker._id self.offsets = offsets self.data_segments = data_segments self.partition = partition self.col, self.row = 0, 0 self.width, self.height = self.partition.cols, self.partition.rows self.pwidth, self.pheight = pwidth, pheight self.conns = connections if rank == 0: log.debug("Worker %d has %s" % (StencilWorker._id, self.partition)) StencilWorker._id += 1 else: self.comm = Communicator(self) def autoconnect(self, wdict, rows=None, cols=None): if self.conns: if self.conns.up: self.conns.up_left = self.conns.up.conns.left self.conns.up_right = self.conns.up.conns.right if self.conns.down: self.conns.down_left = self.conns.down.conns.left self.conns.down_right = self.conns.down.conns.right return tot = int(rows * cols) i_col = self.wid % cols i_row = int(self.wid / cols) start = cols * i_row # Here we calculate our position in the general matrix self.col, self.row = i_col * self.height, i_row * self.width links = [] for wid in ((self.wid + 1) % cols + start, (self.wid - 1) % cols + start, (self.wid - cols) % tot, (self.wid + cols) % tot): if wid == self.wid: links.append(None) else: links.append(wdict[wid]) self.conns = Connections(*links) def __repr__(self): return 'Worker(%d [%d %d %d %d])' % (self.wid, self.row, self.col, self.width, self.height) def start(self): log.info("Worker started on processor %d %s" % (rank, name)) # First we send all the required partitions to the neighbors and then # receive all the segments and reconstruct a local matrix where the # function will be evaluated. puzzle = Puzzle(self.partition) for lbl, enum in zip(LABELS, ORDERED): self.comm.send(getattr(self.conns, lbl), enum) for lbl, enum in zip(RLABELS, REVERSED): m = self.comm.receive(getattr(self.conns, lbl), enum) if m: puzzle.add_piece(m, enum) start = time.time() puzzle.apply(self.offsets, function) log.info("Worker %d: %.10f seconds to compute the partition" % \ (rank - 1, time.time() - start)) log.info("Sending back the computed sub-partition from %d" % rank) start = time.time() comm.gather(self.partition.matrix, root=0) log.info("Worker %d: %.10f seconds to send back the partition" % \ (rank - 1, time.time() - start)) comm.Barrier()