Python MPI与class&;for循环

Python MPI与class&;for循环,python,python-3.x,parallel-processing,mpi,mpi4py,Python,Python 3.x,Parallel Processing,Mpi,Mpi4py,我想用MPI并行处理图中哈密顿路径的计算。 所以,我做到了: from mpi4py import MPI import random,time comm = MPI.COMM_WORLD my_rank = comm.Get_rank() p = comm.Get_size() numOfNodes = 10 numOfProblems = 11 class Graph: def __init__(self, numOfNodes): if numOfNodes &g

我想用MPI并行处理图中哈密顿路径的计算。 所以,我做到了:

from mpi4py import MPI
import random,time

comm = MPI.COMM_WORLD
my_rank = comm.Get_rank()
p = comm.Get_size()
numOfNodes = 10
numOfProblems = 11
class Graph:
    def __init__(self, numOfNodes):
        if numOfNodes > 0:
            self.numOfNodes = numOfNodes
        else:
            print("Error")

    def calculateMaxPairs(self):
        self.maxPairs = self.numOfNodes*(self.numOfNodes - 1)//2

    def generatePairs(self):
        self.calculateMaxPairs()

        self.pairs = []
        startRange = self.numOfNodes
        endRange = (self.numOfNodes - 10)*3 + 18
        numOfPairs = random.randint(startRange, endRange)

        while len(self.pairs) != numOfPairs:
            try:
                startNode = random.randint(1, self.numOfNodes)
                endNode = random.randint(1, self.numOfNodes)
                if startNode == endNode:
                    raise ValueError
            except ValueError:
                pass
            else:
                pair = (startNode, endNode)
                invertedPair = (endNode, startNode)

                if pair not in self.pairs and invertedPair not in self.pairs:
                    self.pairs.append(pair)
        self.hamiltonianPath = []

    def generatePathLink(self):
        self.graphLink = {}
        for x in self.pairs:
            x = str(x)
            splitNode = x.split(', ')
            a = int(splitNode[0][1:])
            b = int(splitNode[1][:-1])
            try:
                if b not in self.graphLink[a]:
                    self.graphLink[a].append(b)
            except KeyError:
                self.graphLink[a] = []
                self.graphLink[a].append(b)
            finally:
                try:
                    if a not in self.graphLink[b]:
                        self.graphLink[b].append(a)
                except KeyError:
                    self.graphLink[b] = []
                    self.graphLink[b].append(a)
                finally:
                    pass

    def findPaths(self, start, end, path = []):
        path = path + [start]
        if start == end:
            return [path]
        if start not in self.graphLink:
            return []
        paths = []
        for node in self.graphLink[start]:
            if node not in path:
                newpaths = self.findPaths(node, end, path)
                for newpath in newpaths:
                    paths.append(newpath)
                    if (len(newpath) == self.numOfNodes):
                        self.hamiltonianPath = newpath
                        raise OverflowError
        return paths

    def exhaustiveSearch(self):
        try:
            allPaths = []
            for startNode in self.graphLink:
                for endNode in self.graphLink:
                    newPaths = self.findPaths(startNode, endNode)
                    for path in newPaths:
                        if (len(path) == self.numOfNodes):
                            allPaths.append(path)
            return allPaths
        except OverflowError:
            return self.hamiltonianPath
        else:
            pass

    def isHamiltonianPathExist(self):
        time_start = time.clock()
        self.generatePathLink()

        if len(self.graphLink) != self.numOfNodes:
            time_elapsed = (time.clock() - time_start)
            return [[], time_elapsed]
        else:
            result = self.exhaustiveSearch()
            time_elapsed = (time.clock() - time_start)
            if len(result) == 0:
                print("There isn't any Hamiltonian Path.")
            else:
                print("Computing time:", round(time_elapsed, 2), "seconds\n")
            return [result, time_elapsed]
            comm.send(result, dest=0)
            

yes = 0
no = 0
total_computing_time = 0
for x in range(1, numOfProblems + 1):
    if my_rank !=0:
        graph = Graph(numOfNodes)
        graph.generatePairs()
        output = graph.isHamiltonianPathExist()
    else:
        for procid in range(1,p):
            result = comm.recv(source=procid)
            time_elapsed = comm.recv(source=procid, tag=12)
            total_computing_time += time_elapsed
            if len(result) == 0:
                no += 1
            else:
                yes += 1

print("Have Hamiltonian Path:", yes)
print("Don't Have Hamiltonian Path:", no)
print("Total computing time for %s problems in %s processes: %s s"%(numOfProblems, p, str(round(total_computing_time, 2))))
正如您在本脚本中看到的,有两个部分。
第一个是我们将生成一个图并计算哈密顿路径。
第二个是我们告诉脚本在多个处理器中并行运行这个图形生成脚本。
这里的问题是,它生成图形并计算每个处理器中的路径,而不是在它们之间划分作业。

我哪里做错了?

为什么要使用
!=0
?它需要
==0
才能仅在第一个过程中创建图形。对于我来说,第一个进程应该发送
范围(1,numOfProblems+1)
,另一个进程应该创建自己的
图形
,计算接收值的路径,并将结果发送回。这意味着,如果我的秩==0:,则的
循环应该在
内部,而不是
外部,如果
。我认为主要问题是您期望太高-MPI不会自动在进程之间划分作业-您必须这样做。如果要为不同数量的节点计算图形,则必须向每个进程发送不同数量的节点,每个进程都必须接收并为自己数量的节点创建自己的图形,计算并发回结果。问题是当您的值比进程多时,因为您必须多次使用某些进程,并且您必须手动执行,或者您应该使用
Pool
,就像在模块
threading
mulitprocessing
中一样。顺便说一句:我不明白为什么要使用
x=str(x)
splitNode=x.split(','))
a=int(splitNode[0][1:])
b=int(splitNode[1][:-1])
如果你能简单地
a=x[0]
b=x[1]
甚至
a,b=x