def bb(adjacency, p=1): n = len(adjacency) comm = PSim(p) Q = [] path = [0] Q.append(Vertex(path)) bound = float("inf') optimal = None local_vertices = comm.one2all_scatter(0, range(n)) while True: if comm.rank == 0: vertex = Q.pop() if Q else None else: vertex = None vertex = comm.one2all_broadcast(0, vertex) if vertex is None: break P = [] for k in local_vertices: if not k in vertex.path: new_path = vertex.path+[k] new_path_length = weight(new_path, adjacency) if new_path_length<bound: if len(new_path) == n: new_path.append(new_path[0]) new_path_length = weight(new_path, adjacency) if new_path_length<bound: bound = new_path_length # bcast optimal = new_path # bcast else: new_vertex = Vertex(new_path) P.append(new_vertex) # fix this print(new_path, new_path_length) x = (bound, optimal) x = comm.all2all_reduce(x, lambda a, b: min(a, b)) (bound, optimal) = x P = comm.all2one_collect(0, P) if comm.rank == 0: for item in P: Q+=item return optimal, bound
def dijkstra_p(g, source, p): """ PYsim parallel implementation of dijkstra's algorithm Result: One source shourtest paths to all nodes Implementation parallelizes finding minimums and updating the results (inner loop is parallelized) Uses the method of collecting of intermediate minimums and broadcasting of newly found path to all processes """ # Initialize communicator comm = PSim(p) myRank = comm.rank chunkSize = len(g) / p # Scatter the graph by partitioning it one dimensionally, # along with known distances to source, and remaining node information myGraphChunk = comm.one2all_scatter(0, g) localResultView = comm.one2all_scatter(0, g[source]) localRemainView = comm.one2all_scatter(0, g[source]) # Each process will iterate q times, where q is number of nodes in graph for q in range(len(g)): # Get shortest path to locally un-visited nodes lowestLocalDist = min(localRemainView) lowestLocalDistIdx = localRemainView.index(lowestLocalDist) # Collect the lowest distances and node indexes from all processes gatheredCandidatesDist = comm.all2one_collect(0, lowestLocalDist) gatheredCandidatesIdxs = comm.all2one_collect(0, lowestLocalDistIdx + myRank * chunkSize) processWithLowestDist = -1 addedNodeIdx = -1 lowestOverallDistance = -1 # One 'main' process finds the global minimum if myRank == 0: lowestOverallDistance = min(gatheredCandidatesDist) processWithLowestDist = gatheredCandidatesDist.index(lowestOverallDistance) addedNodeIdx = gatheredCandidatesIdxs[processWithLowestDist] # 'Main' process broadcasts the finding to all processes receivedBroadcast = comm.one2all_broadcast(0, (processWithLowestDist, addedNodeIdx, lowestOverallDistance)) # If this process is responsible for the newly found shortest path, # then mark this node as visited. if myRank == receivedBroadcast[0]: indexToUpdate = receivedBroadcast[1] - myRank * chunkSize localRemainView[indexToUpdate] = "" # Each process loop over all connections to this last visited node # that they have the visibility to. for iter in range(len(localResultView)): potentialNewDistance = myGraphChunk[iter][receivedBroadcast[1]] + receivedBroadcast[2] # If the distances through this node are less than what we know if potentialNewDistance < localResultView[iter]: # Update the local portion of the result list and # remaining nodes list localResultView[iter] = potentialNewDistance localRemainView[iter] = potentialNewDistance # Reduce the final result to a single list and return it reassembled = comm.all2one_reduce(0, localResultView) if myRank == 0: return reassembled else: return []
def dijkstra_p(g, source, p): """ PYsim parallel implementation of dijkstra's algorithm Result: One source shourtest paths to all nodes Implementation parallelizes finding minimums and updating the results (inner loop is parallelized) Uses the method of collecting of intermediate minimums and broadcasting of newly found path to all processes """ # Initialize communicator comm = PSim(p) myRank = comm.rank chunkSize = len(g) / p # Scatter the graph by partitioning it one dimensionally, # along with known distances to source, and remaining node information myGraphChunk = comm.one2all_scatter(0, g) localResultView = comm.one2all_scatter(0, g[source]) localRemainView = comm.one2all_scatter(0, g[source]) # Each process will iterate q times, where q is number of nodes in graph for q in range(len(g)): # Get shortest path to locally un-visited nodes lowestLocalDist = min(localRemainView) lowestLocalDistIdx = localRemainView.index(lowestLocalDist) # Collect the lowest distances and node indexes from all processes gatheredCandidatesDist = comm.all2one_collect(0, lowestLocalDist) gatheredCandidatesIdxs = comm.all2one_collect( 0, lowestLocalDistIdx + myRank * chunkSize) processWithLowestDist = -1 addedNodeIdx = -1 lowestOverallDistance = -1 # One 'main' process finds the global minimum if myRank == 0: lowestOverallDistance = min(gatheredCandidatesDist) processWithLowestDist = gatheredCandidatesDist.index( lowestOverallDistance) addedNodeIdx = gatheredCandidatesIdxs[processWithLowestDist] # 'Main' process broadcasts the finding to all processes receivedBroadcast = \ comm.one2all_broadcast(0,\ (processWithLowestDist,addedNodeIdx,lowestOverallDistance,)) # If this process is responsible for the newly found shortest path, # then mark this node as visited. if myRank == receivedBroadcast[0]: indexToUpdate = receivedBroadcast[1] - myRank * chunkSize localRemainView[indexToUpdate] = '' # Each process loop over all connections to this last visited node # that they have the visibility to. for iter in range(len(localResultView)): potentialNewDistance = \ myGraphChunk[iter][receivedBroadcast[1]]+receivedBroadcast[2] # If the distances through this node are less than what we know if potentialNewDistance < localResultView[iter]: # Update the local portion of the result list and # remaining nodes list localResultView[iter] = potentialNewDistance localRemainView[iter] = potentialNewDistance # Reduce the final result to a single list and return it reassembled = comm.all2one_reduce(0, localResultView) if myRank == 0: return reassembled else: return []
MST = [] #minimum spanning tree to return total_worker_trees = 0 edges_processed = 0; cont_parallel = True cont_serial = False while cont_parallel: #for i in sorted_edges: if len(sorted_edges)==0: cont_parallel = False else: curr_edge = sorted_edges.pop(0) #command for workers to be sent with message cmnd = 1 v1, v2, w = curr_edge #send the vertices to the workers so they can search their local forest comm.one2all_broadcast(0,(cmnd,v1,v2)) add = False send_union_tree = False #if vertices are in different worker's forests, must get the rank of the #worker with vertex_1 and both trees to union and send to that worker worker = -1 half_tree_1 = [] half_tree_2 = [] #loop through all of the worker responses for r in range(1,p): total_worker_trees = 0 resp = comm.recv(r) if resp[0] == 0: b=1 #print 'worker: ', r, ' does not have these vertices in their forest' elif resp[0] == 1:
MST = [] #minimum spanning tree to return total_worker_trees = 0 edges_processed = 0 cont_parallel = True cont_serial = False while cont_parallel: #for i in sorted_edges: if len(sorted_edges) == 0: cont_parallel = False else: curr_edge = sorted_edges.pop(0) #command for workers to be sent with message cmnd = 1 v1, v2, w = curr_edge #send the vertices to the workers so they can search their local forest comm.one2all_broadcast(0, (cmnd, v1, v2)) add = False send_union_tree = False #if vertices are in different worker's forests, must get the rank of the #worker with vertex_1 and both trees to union and send to that worker worker = -1 half_tree_1 = [] half_tree_2 = [] #loop through all of the worker responses for r in range(1, p): total_worker_trees = 0 resp = comm.recv(r) if resp[0] == 0: b = 1 #print 'worker: ', r, ' does not have these vertices in their forest' elif resp[0] == 1: