Seite 1 von 1

Newbie braucht Hilfe bei Laufzeitoptimierung

Verfasst: Freitag 16. Januar 2015, 16:49
von PhilipLane
Hallo Leute,

ich bin eigentlich noch ein absoluter Anfänger in der Programmierung und ich arbeite mich nun seit zwei Monaten in Python3 ein.
Ich möchte ein Programm schreiben, das Zufallszahlen x_1 bis x_5 erzeugt, die einer bestimmten Verteilung unterliegen.
beispielsweise ist x_1 dreieckverteilt, x_2 normalverteilt, usw und damit werden dann Zufallszahlen y = f(x_1,...,x_5) berechnet,
wobei f irgendeine Funktion ist. Anschließend sollen die Werte für y in einem Histogramm ausgegeben werden.
Das Programm läuft auch bereits, aber bislang habe ich für f nur die vier Grundrechenarten und Potenzen verwendet.

Nun habe ich ein Problem, wenn ich aus numpy mathematische Funktionen wie cos, sin und exp verwenden will.
Mein Problem besteht darin, dass die Laufzeit bei 3*10**5 Zufallszahlen bis zu 180 Sekunden und teilweise noch länger beträgt.

Hier einmal ein Minimalbeispiel, dass bei mir nach 10 Minuten noch kein Histogramm zum Vorschein bringt.

Code: Alles auswählen

import random
import matplotlib.pyplot as plt
import sympy
import time

Timestamp_1 = time.time()    

Data = [ float(sympy.sin(random.triangular(0, 5, 10)))  for i in range(0, 3*10**5) ]

plt.hist(Data ,bins = 55, color='maroon', normed=True)
plt.title('Error Distribution')
plt.xlabel('x-Achse')
plt.ylabel("Probability")
plt.show()

Timestamp_2 = time.time()

T=round(Timestamp_2 - Timestamp_1,2)
print('Laufzeit:', T)
Ich habe bereits im Internet und hier im Forum ein wenig gesucht und dabei gelesen, dass das random-Modul in Python sehr langsam sein soll, dass es aber hin und wieder
Wege und Möglichkeiten gibt, die Laufzeit zu optimieren. Daher wollte ich einmal fragen, ob das bei meinem Vorhaben auch möglich ist und ob jemand
einen effektiveren Weg sieht, ein solches Histogramm zu erstellen.

Schon einmal vielen lieben Dank im Voraus!

Re: Newbie braucht Hilfe bei Laufzeitoptimierung

Verfasst: Freitag 16. Januar 2015, 16:57
von EyDu
Hallo und willkommen im Forum!

Nimm doch einfach NumPy, das braucht dafür quasi keine Zeit:

Code: Alles auswählen

numpy.random.triangular(0, 5, 10, size=3*10**5)
SymPy ist dafür einfach die falsche Bibliothek, die ist für symbolisches Rechnen gedacht. Das random-Modul an sich ist nicht langsam.

Edit: SciPy in SymPy geändert.

Re: Newbie braucht Hilfe bei Laufzeitoptimierung

Verfasst: Freitag 16. Januar 2015, 17:03
von BlackJack
@EyDu: Pssst, Du hast SciPy geschrieben, meintest aber sicher Sympy. ;-)

Re: Newbie braucht Hilfe bei Laufzeitoptimierung

Verfasst: Freitag 16. Januar 2015, 17:05
von PhilipLane
Wow, danke!
Ich wusste nicht, dass Numpy soetwas auch kann!

Code: Alles auswählen

Data = [ float(numpy.sin(numpy.random.triangular(0, 5, 10)))  for i in range(0,10**5)]

plt.hist(Data ,bins = 55, color='maroon', normed=True)
plt.title('Error Distribution')
plt.xlabel('x-Achse')
plt.ylabel("Probability")
plt.show()
Nun benötige ich nur eine Laufzeit von 0.69 Sekunden!
Du hast mir gerade echt den Abend gerettet!

Re: Newbie braucht Hilfe bei Laufzeitoptimierung

Verfasst: Freitag 16. Januar 2015, 17:07
von BlackJack
@PhilipLane: Und jetzt verwende mal das was EyDu geschrieben hat, also *wirklich* Numpy verwenden und nicht dann doch wieder eine Liste erstellen und ganz viele unnötige `float()`-Aufrufe machen. ;-)

Re: Newbie braucht Hilfe bei Laufzeitoptimierung

Verfasst: Freitag 16. Januar 2015, 17:13
von PhilipLane
Okay, danke.

Ich sehe gerade, dass man bei numpy das float weglassen kann.
Bei sympy musste man es dazuschreiben, weil sonst beim Erstellen des Histogramms ein DataType-Fehler auftrat.
Anscheinend benutzt sympy für Zahlen einen anderen Datentyp als Python selbst und das musste mit float() umgewandelt werden.
Stand zumindest irgendwo bei stack-overflow und hat bei mir auch funktioniert.

Aber um das Erstellen einer Liste komme ich doch nicht herum, oder?

Ich kann ja mit dem Code von EyDu nur eine Liste von dreieckverteilten Zufallszahlen erstellen.
Wenn ich aber ein Histogramm für y = sin( Zufallszahl ) haben möchte, muss ich jede der Zufallszahlen doch verrechnen und zuerst in
eine Liste speichern, die ich dann als Histogramm darstelle. Oder geht das auch irgendwie einfacher?

Re: Newbie braucht Hilfe bei Laufzeitoptimierung

Verfasst: Freitag 16. Januar 2015, 17:18
von BlackJack
@PhilipLane: Numpy funktioniert zwar auch mit Einzelwerten aber hauptsächlich ist die Bibliothek zum Rechnen mit Arrays gedacht. Wenn Du ein Numpy-Array hast und etwas mit allen Zahlen in diesem Array machen möchtest, dann wendest Du die entsprechende Operation oder Numpy-Funktion einfach auf das Array an. Also:

Code: Alles auswählen

data = numpy.sin(numpy.random.triangular(0, 5, 10, size=10**5))

Re: Newbie braucht Hilfe bei Laufzeitoptimierung

Verfasst: Freitag 16. Januar 2015, 17:21
von PhilipLane
BlackJack hat geschrieben:Wenn Du ein Numpy-Array hast und etwas mit allen Zahlen in diesem Array machen möchtest, dann wendest Du die entsprechende Operation oder Numpy-Funktion einfach auf das Array an.
Das wusste ich nicht, aber ich finde es toll, wie einfach es ist! :D
Ich werde mich dann über das Wochenende mal mit numpy befassen.

Vielen lieben Dank! Ihr habt mir gerade echt aus der Patsche geholfen!

Schönes Wochenende,
Kevin

Re: Newbie braucht Hilfe bei Laufzeitoptimierung

Verfasst: Freitag 16. Januar 2015, 17:30
von EyDu
BlackJack hat geschrieben:@EyDu: Pssst, Du hast SciPy geschrieben, meintest aber sicher Sympy. ;-)
Danke, natürlich. Da waren die Hände schneller als das Gehirn.