Frage

Ich repliziere ein kleines Stück des Sugarscape-Agentensimulationsmodells in Python 3. Ich habe festgestellt, dass die Leistung meines Codes etwa dreimal langsamer ist als die von NetLogo. Ist es wahrscheinlich das Problem mit meinem Code oder kann es die inhärente Einschränkung von Python sein?

Natürlich ist dies nur ein Fragment des Codes, aber hier verbringt Python zwei Drittel der Laufzeit. Ich hoffe, wenn ich etwas wirklich Ineffizientes geschrieben habe, könnte es in diesem Fragment auftauchen:

UP = (0, -1)
RIGHT = (1, 0)
DOWN = (0, 1)
LEFT = (-1, 0)
all_directions = [UP, DOWN, RIGHT, LEFT]
# point is just a tuple (x, y)
def look_around(self):
    max_sugar_point = self.point
    max_sugar = self.world.sugar_map[self.point].level
    min_range = 0

    random.shuffle(self.all_directions)
    for r in range(1, self.vision+1):
        for d in self.all_directions:
            p = ((self.point[0] + r * d[0]) % self.world.surface.length,
                (self.point[1] + r * d[1]) % self.world.surface.height)
            if self.world.occupied(p): # checks if p is in a lookup table (dict)
                continue
            if self.world.sugar_map[p].level > max_sugar:
                max_sugar = self.world.sugar_map[p].level
                max_sugar_point = p
    if max_sugar_point is not self.point:
        self.move(max_sugar_point)

Ungefähr gleichwertiger Code in NetLogo (dieses Fragment bietet etwas mehr als die oben beschriebene Python-Funktion) :

; -- The SugarScape growth and motion procedures. --
to M    ; Motion rule (page 25)
    locals [ps p v d]
    set ps (patches at-points neighborhood) with [count turtles-here = 0]
    if (count ps > 0) [
        set v psugar-of max-one-of ps [psugar]              ; v is max sugar w/in vision
        set ps ps with [psugar = v]                         ; ps is legal sites w/ v sugar
        set d distance min-one-of ps [distance myself]      ; d is min dist from me to ps agents
        set p random-one-of ps with [distance myself = d]   ; p is one of the min dist patches
        if (psugar >= v and includeMyPatch?) [set p patch-here]
        setxy pxcor-of p pycor-of p                         ; jump to p
        set sugar sugar + psugar-of p                       ; consume its sugar
        ask p [setpsugar 0]                                 ; .. setting its sugar to 0
    ]
    set sugar sugar - metabolism    ; eat sugar (metabolism)
    set age age + 1
end

Auf meinem Computer benötigt der Python-Code 15,5 Sekunden, um 1000 Schritte auszuführen. Auf demselben Laptop führt die in Java im Browser ausgeführte NetLogo-Simulation 1000 Schritte in weniger als 6 Sekunden aus.

BEARBEITEN: Nur Repast mit Java-Implementierung aktiviert. Und es ist auch ungefähr das gleiche wie NetLogo bei 5,4 Sekunden. Aktuelle Vergleiche zwischen Java und Python lassen keinen Vorteil für Java erkennen Also, ich denke, es ist nur mein Code, der schuld ist?

BEARBEITEN: Ich verstehe, dass MASON sogar noch schneller sein soll als Repast, und dennoch läuft am Ende immer noch Java.

War es hilfreich?

Lösung

Dies führt wahrscheinlich nicht zu dramatischen Beschleunigungen, aber Sie sollten sich bewusst sein, dass lokale Variablen in Python viel schneller sind als der Zugriff auf globale oder Attribute.Sie können also versuchen, den Einheimischen einige Werte zuzuweisen, die in der inneren Schleife verwendet werden:

def look_around(self):
    max_sugar_point = self.point
    max_sugar = self.world.sugar_map[self.point].level
    min_range = 0

    selfx = self.point[0]
    selfy = self.point[1]
    wlength = self.world.surface.length
    wheight = self.world.surface.height
    occupied = self.world.occupied
    sugar_map = self.world.sugar_map
    all_directions = self.all_directions

    random.shuffle(all_directions)
    for r in range(1, self.vision+1):
        for dx,dy in all_directions:
            p = ((selfx + r * dx) % wlength,
                (selfy + r * dy) % wheight)
            if occupied(p): # checks if p is in a lookup table (dict)
                continue
            if sugar_map[p].level > max_sugar:
                max_sugar = sugar_map[p].level
                max_sugar_point = p
    if max_sugar_point is not self.point:
        self.move(max_sugar_point)

Funktionsaufrufe in Python haben auch einen relativ hohen Overhead (im Vergleich zu Java), sodass Sie versuchen können, weiter zu optimieren, indem Sie die occupied-Funktion durch eine direkte Wörterbuchsuche ersetzen.

Sie sollten sich auch psyco ansehen.Es ist ein Just-in-Time-Compiler für Python, der in einigen Fällen zu dramatischen Geschwindigkeitsverbesserungen führen kann.Python 3.x wird jedoch noch nicht unterstützt, sodass Sie eine ältere Version von Python verwenden müssen.

Andere Tipps

Ich gehe davon aus, dass sich die Art und Weise, wie neighborhood in NetLogo implementiert wird, von der Doppelschleife unterscheidet, die Sie haben.Insbesondere denke ich, dass sie einen Nachbarschaftsvektor wie vorberechnen

n = [ [0,1],[0,-1],[1,0],[-1,0]....]

(Sie benötigen eine andere für vision= 1,2, ...) und verwenden dann nur eine Schleife über n anstelle einer verschachtelten Schleife, wie Sie es tun.Dies macht die Multiplikationen überflüssig.

Ich glaube nicht, dass Sie dadurch dreimal schneller werden.

Dies ist eine alte Frage, aber ich schlage vor, dass Sie NumPy verwenden, um Ihre Vorgänge zu beschleunigen.Orte, an denen Sie Diktate und Listen verwenden, die logisch organisiert sind (1-, 2-, 3- oder N-dimensionales Raster), homogenes Datenobjekt (alle Ganzzahlen oder alle Gleitkommazahlen usw.) haben weniger Aufwand, wenn sie als Numpy dargestellt und aufgerufen werdenArrays.

http://numpy.org

Hier ist ein relativ aktueller Vergleich von NetLogo und einer Version von Repast.Ich würde nicht unbedingt annehmen, dass Repast schneller ist.NetLogo scheint einige sehr intelligente Algorithmen zu enthalten, die die damit verbundenen Kosten ausgleichen können. http://condor.depaul.edu/slytinen/abm/Lytinen-Railsback-EMCSR_2012-02-17.pdf

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top