parallel computing (Dan Bader)

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Benutzeravatar
pixewakb
User
Beiträge: 1412
Registriert: Sonntag 24. April 2011, 19:43

Heute bekam ich eine E-Mail von Dan Bader zum Thema parallel computing mit folgendem Quellcode-Beispiel:

Code: Alles auswählen

import collections
import multiprocessing

Scientist = collections.namedtuple('Scientist', [
    'name',
    'born',
])

scientists = (
    Scientist(name='Ada Lovelace', born=1815),
    Scientist(name='Emmy Noether', born=1882),
    Scientist(name='Marie Curie', born=1867),
    Scientist(name='Tu Youyou', born=1930),
    Scientist(name='Ada Yonath', born=1939),
    Scientist(name='Vera Rubin', born=1928),
    Scientist(name='Sally Ride', born=1951),
)

def process_item(item):
    return {
        'name': item.name,
        'age': 2017 - item.born
    }

pool = multiprocessing.Pool()
result = pool.map(process_item, scientists)

print(tuple(result))
Ich habe meinen Rechner noch nie so aufheulen hören, aber auf eine Ausgabe der Konsole warte ich immer noch. Hat jemand eine Idee, woran das liegt (Windows 10)? Ich habe noch keine Aufgabe, die ich mit parallel computing bewältigen möchte, momentan geht es eher um Erweiterung meiner Möglichkeiten...
__deets__
User
Beiträge: 14539
Registriert: Mittwoch 14. Oktober 2015, 14:29

Unter dem mac tut's fuer mich ohne probleme. Hast du es mal mit print-Debugging probiert?
Benutzeravatar
pixewakb
User
Beiträge: 1412
Registriert: Sonntag 24. April 2011, 19:43

Was meinst Du mit print-Debugging? <s>Ich google mal, ob das ein...</s>

Ich habe festgestellt, dass ich es nicht mit IDLE laufen lassen kann, direkt über die Konsole liefert es mir aber auch nur eine Fülle von Fehlermeldungen in der Konsole. Danke erst einmal, das ist momentan nichts, was ich dringend produktiv benötige, eher Grundlagenforschung :D
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

@pixewakb: das Hauptprogramm muß durch `if __name__ == '__main__'` geschützt werden, weil Windows einfach mehrere Pythonprogramme startet, statt zu clonen.
Den Kommentar zu selbsternannten Python-Experten verkneif ich mir.
Benutzeravatar
pixewakb
User
Beiträge: 1412
Registriert: Sonntag 24. April 2011, 19:43

@Sirius3: Ich habe kein Informatik studiert und komme aus einer ganz anderen Ecke. Ich nutze Python momentan hauptsächlich, um bestimmte Aufgaben effizient und schnell zu bewältigen. Ansonsten sehe ich mich eher auf einem langen Weg und bin hier für die Rückmeldung und die Tipps sehr dankbar. Wenn ich hier auf Fragen antworte, dann ist es der Versuch meinerseits etwas zurückzugeben.

Für die Konsole habe ich mal Folgendes getestet:

Code: Alles auswählen

# -*- coding: utf-8 -*-
#!/usr/bin/env python3
import collections
import multiprocessing


def process_item(item):
    return {
        'name': item.name,
        'age': 2017 - item.born
    }


def main():
    Scientist = collections.namedtuple('Scientist', [
        'name',
        'born',
    ])

    scientists = (
        Scientist(name='Ada Lovelace', born=1815),
        Scientist(name='Emmy Noether', born=1882),
        Scientist(name='Marie Curie', born=1867),
        Scientist(name='Tu Youyou', born=1930),
        Scientist(name='Ada Yonath', born=1939),
        Scientist(name='Vera Rubin', born=1928),
        Scientist(name='Sally Ride', born=1951),
    )

    pool = multiprocessing.Pool()
    result = pool.map(process_item, scientists)


    print(tuple(result))


if __name__ == '__main__':

    main()

    input(">>> ")
und sehe dann diese Rückmeldung:

Code: Alles auswählen

Traceback (most recent call last):
  File "main0001.py", line 39, in <module>
    main()
  File "main0001.py", line 31, in main
    result = pool.map(process_item, scientists)
  File "C:\[...]\lib\multiprocessing\pool.py", line 268, in map
    return self._map_async(func, iterable, mapstar, chunksize).get()
  File "C:\[...]\lib\multiprocessing\pool.py", line 657, in get
    raise self._value
  File "C:\[...]\lib\multiprocessing\pool.py", line 431, in _handle_tasks
    put(task)
  File "C:\[...]\lib\multiprocessing\connection.py", line 206, in send
    self._send_bytes(_ForkingPickler.dumps(obj))
  File "C:\[...]\lib\multiprocessing\reduction.py", line 51, in dumps
    cls(buf, protocol).dump(obj)
_pickle.PicklingError: Can't pickle <class '__main__.Scientist'>: attribute lookup Scientist on __main__ failed
Aus meiner Sicht sieht mein Skript korrekt aus und ich würde dann hier eigentlich erwarten, dass es dann auch durchläuft? Wie gesagt, im Moment ist es für mich eine Spielerei, das ist weit weg von dem, was ich eigentlich mache...
__deets__
User
Beiträge: 14539
Registriert: Mittwoch 14. Oktober 2015, 14:29

Niemand hat gesagt, dass du die Klassendefinition *IN* die Funktion main packen sollst. Enstprechend wird die nicht gefunden von den anderen Prozessen.
Benutzeravatar
pixewakb
User
Beiträge: 1412
Registriert: Sonntag 24. April 2011, 19:43

DANKE!!! Das läuft jetzt:

Code: Alles auswählen

# -*- coding: utf-8 -*-
#!/usr/bin/env python3
import collections
import multiprocessing

def process_item(item):
    return {
        'name': item.name,
        'age': 2017 - item.born
    }

Scientist = collections.namedtuple('Scientist', [
    'name',
    'born',
])

def main():

    scientists = (
        Scientist(name='Ada Lovelace', born=1815),
        Scientist(name='Emmy Noether', born=1882),
        Scientist(name='Marie Curie', born=1867),
        Scientist(name='Tu Youyou', born=1930),
        Scientist(name='Ada Yonath', born=1939),
        Scientist(name='Vera Rubin', born=1928),
        Scientist(name='Sally Ride', born=1951),
    )

    pool = multiprocessing.Pool()
    result = pool.map(process_item, scientists)

    print(tuple(result))

if __name__ == '__main__':
    main()
    input(">>> ")
Ich hatte heute nicht erwartet, dass ich bei einem Beispielprogramm noch nachbessern müsste. Vielleicht finde ich mal was, wo ich es produktiv einsetzen kann. Jedenfalls: Ganz herzlichen Dank für die Rückmeldungen! :!:
Benutzeravatar
pixewakb
User
Beiträge: 1412
Registriert: Sonntag 24. April 2011, 19:43

Rein aus Interesse: Setzt ihr parallel computing in eurer praktischen Arbeit ein und falls ja, bei welchen Aufgaben? Ich sehe für mich noch keinen direkten Einsatzzweck, wahrscheinlich sind meine Berechnungen aber auch zu überschaubar, als dass ich einen sinnvollen Einsatz hätte...???
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

@pixewakb: Bei asynchron laufenden Anwendungen (z.B. Tornado) lässt sich Nebenläufigkeit für blockierende Operationen nutzen. Oder für Monte-Carlo Simulationen, wenn Ergebnisse nebenher berechnet werden können und nicht aufeinander aufbauen. Oder für die Auswertung großer Datenmengen, für die das gleiche gilt. Dann gibt es aber auch Anwendungen, bei denen kann Nebenläufigkeit nicht angewendet werden, oder hat keinen Vorteil. Das Skript von Dan Bader ist ein solches. Es zeigt nur den Mechanismus an einem ungeeigneten Beispiel (mit dem Fehler, auf den Sirius3 hingewiesen hat und auf den auch deutlich in der Python-Dokumentation hingewiesen wird).
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

Für asynchrone Anwendungen nimmt man heutzutage asyncio oder ähnliche Bibliotheken, weil die resourcenschonender, vorhersagbarer und einfacher in der Anwendung sind.
Für GUIs mit einem Vordergrundprozess und einer im Hintergrund ablaufenden Rechnung, bietet sich `threading` an.
Für Rechnungen mit großen Matrizen kommt z.B. numpy mit mkl zum Einsatz, das die Rechnung effizient auf mehrere Kerne verteilen kann.
Für multiprocessing bleibt eigentlich nur noch komplexere Simulationen, die nicht gut mit mkl parallelisierbar sind und wenig nicht voneinander abhängen.
Benutzeravatar
__blackjack__
User
Beiträge: 13103
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Ich benutze es selten. Eben dann wenn es a) Sinn macht und b) die nicht-parallele Variante tatsächlich zu langsam ist. Wenn dann läuft das meistens so ab, das ich erst eine sequentielle Variante programmiere und erst wenn klar ist, dass das ausreichend oft läuft eventuell parallelisiere. Denn die Zeit die man braucht um das zusätzlich im Programm umzusetzen, muss bei den den tatsächlichen Programmläufen ja wieder rein kommen, sonst ist das ein Minusgeschäft. Und selbst wenn die Zeit wieder rein kommt, ist auch noch die Frage ob man tatsächlich etwas davon hat. Ob ein Cronjob, der nachts um 2 automatisch läuft, 40 Minuten lang einen Prozessorkern beschäftigt oder nur 10 Minuten lang vier Kerne beschäftigt ist oft auch einfach völlig egal.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Antworten