Summieren von Python-Objekten mit MPI's Allreduce

Ich benutze eine spärliche Tensor Array Manipulation Ich baute mit Wörterbüchern und Zähler in Python. Ich möchte es möglich machen, diese Array-Manipulation parallel zu verwenden. Die untere Zeile ist, dass ich am Ende mit Zähler auf jedem Knoten, die ich möchte zusammen mit MPI.Allreduce (oder eine andere schöne Lösung). Zum Beispiel mit Zähler kann man das machen

A = Counter({a:1, b:2, c:3}) B = Counter({b:1, c:2, d:3}) 

so dass

  • Mpi4py: schließen MPI Spawn?
  • Mpi4py: Kommunikation zwischen hervorgebrachten Prozessen
  • Ist es möglich, Daten von einem Fortran-Programm zu Python mit MPI zu senden?
  • Python-Multiprocessing innerhalb von mpi
  • Hallo_World nicht mit mpi4py auf Cluster spielen: II
  • MPI Bcast oder Scatter zu bestimmten Rängen
  •  C = A+B = Counter({a:1, b:3, c:5, d:3}). 

    Ich möchte die gleiche Operation machen, aber mit allen relevanten Knoten,

     MPI.Allreduce(send_counter, recv_counter, MPI.SUM) 

    Allerdings scheint MPI nicht zu erkennen, diese Operation auf Wörterbücher / Zähler, werfen einen Fehler expecting a buffer or a list/tuple . Ist meine beste Option ein "Benutzerdefinierter Betrieb" oder gibt es einen Weg, um Allreduce zu bekommen, um Zähler hinzuzufügen? Vielen Dank,

    EDIT (7/14/15): Ich habe versucht, eine Benutzeroperation für Wörterbücher zu erstellen, aber es gab einige Diskrepanzen. Ich schrieb folgendes

     def dict_sum(dict1, dict2, datatype): for key in dict2: try: dict1[key] += dict2[key] except KeyError: dict1[key] = dict2[key] 

    Und als ich MPI über die Funktion erzählte, habe ich das gemacht:

     dictSumOp = MPI.Op.Create(dict_sum, commute=True) 

    Und in dem Code habe ich es als benutzt

     the_result = comm.allreduce(mydict, dictSumOp) 

    Allerdings warf es unsupported operand '+' for type dict . So schrieb ich

     the_result = comm.allreduce(mydict, op=dictSumOp) 

    Und nun wirft es dict1[key] += dict2[key] TypeError: 'NoneType' object has no attribute '__getitem__' so scheinbar will es wissen, dass diese Wörter Wörterbücher sind? Wie kann ich sagen, sie haben Typ Wörterbuch?

  • Wie man alle Integer in der Liste vermehrt
  • Pythonlistenmultiplikation: [[...]] * 3 macht 3 Listen, die sich gegenseitig spiegeln, wenn sie modifiziert werden [duplizieren]
  • Wie kann ich alle Artikel in einer Liste zusammen mit Python multiplizieren?
  • One Solution collect form web for “Summieren von Python-Objekten mit MPI's Allreduce”

    Weder MPI noch MPI4py weiß etwas über Counters im Besonderen, also musst du deinen eigenen Reduktionsbetrieb für diese Arbeit erstellen! Dies wäre das gleiche für jede andere Art von Python-Objekt:

     #!/usr/bin/env python from mpi4py import MPI import collections def addCounter(counter1, counter2, datatype): for item in counter2: counter1[item] += counter2[item] return counter1 if __name__=="__main__": comm = MPI.COMM_WORLD if comm.rank == 0: myCounter = collections.Counter({'a':1, 'b':2, 'c':3}) else: myCounter = collections.Counter({'b':1, 'c':2, 'd':3}) counterSumOp = MPI.Op.Create(addCounter, commute=True) totcounter = comm.allreduce(myCounter, op=counterSumOp) print comm.rank, totcounter 

    Hier haben wir eine Funktion genommen, die zwei Gegenobjekte zusammenfasst und einen MPI-Operator aus ihnen mit MPI.Op.Create erstellt hat. Mpi4py wird die Objekte entpickeln, diese Funktion ausführen, um diese Elemente paarweise zu kombinieren, dann das Teilergebnis zu pflücken und an die nächste Aufgabe zu senden.

    Beachten Sie auch, dass wir (Kleinbuchstaben) allreduce, die auf beliebigen Pythonobjekten arbeitet, anstatt (Großbuchstaben) Allreduce, die auf numpy Arrays oder ihre moralischen Äquivalente (Puffer, die Karte auf die Fortran / C Arrays, dass die MPI API Ist entworfen auf).

    Laufen gibt:

     $ mpirun -np 2 python ./counter_reduce.py 0 Counter({'c': 5, 'b': 3, 'd': 3, 'a': 1}) 1 Counter({'c': 5, 'b': 3, 'd': 3, 'a': 1}) $ mpirun -np 4 python ./counter_reduce.py 0 Counter({'c': 9, 'd': 9, 'b': 5, 'a': 1}) 2 Counter({'c': 9, 'd': 9, 'b': 5, 'a': 1}) 1 Counter({'c': 9, 'd': 9, 'b': 5, 'a': 1}) 3 Counter({'c': 9, 'd': 9, 'b': 5, 'a': 1}) 

    Und mit nur bescheidenen Änderungen arbeitet mit einem generischen Wörterbuch:

     #!/usr/bin/env python from mpi4py import MPI def addCounter(counter1, counter2, datatype): for item in counter2: if item in counter1: counter1[item] += counter2[item] else: counter1[item] = counter2[item] return counter1 if __name__=="__main__": comm = MPI.COMM_WORLD if comm.rank == 0: myDict = {'a':1, 'c':"Hello "} else: myDict = {'c':"World!", 'd':3} counterSumOp = MPI.Op.Create(addCounter, commute=True) totDict = comm.allreduce(myDict, op=counterSumOp) print comm.rank, totDict 

    Laufen geben

     $ mpirun -np 2 python dict_reduce.py 0 {'a': 1, 'c': 'Hello World!', 'd': 3} 1 {'a': 1, 'c': 'Hello World!', 'd': 3} 
    Python ist die beste Programmiersprache der Welt.