Primzahlenrechner

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.
Sirius3
User
Beiträge: 17753
Registriert: Sonntag 21. Oktober 2012, 17:20

@nooby: der Fehler liegt in dieser Zeile:

Code: Alles auswählen

pool.apply_async(generate_save_primes(start, ende, primes_filename))
die Du auch so schreiben könntest:

Code: Alles auswählen

result=generate_save_primes(start, ende, primes_filename)
pool.apply_async(result)
Der Rückgabewert von generate_save_primes ist übrigens »None«.
Du mußt »apply_async« eine Funktion und nicht das Ergebnis eines Funktionsaufrufs übergeben:

Code: Alles auswählen

pool.apply_async(generate_save_primes, args=(start, ende, primes_filename))
Damit werden Deine Primzahlen aber immer noch nur in einem Process berechnet.
nooby
User
Beiträge: 91
Registriert: Montag 12. März 2012, 20:39
Wohnort: 127.0.0.1

@Sirius3:
Ok, danke für deine Antwort. Jetzt ist es mit klar.

Wenn ich die Prozesse unterteilen muss, ist es dann besser auszulesen, wie viele Kerne die betreffende CPU hat, oder kann ich einfach in z.B. 8 Teile spliten und Pool verteilt es dann auf CPU Kerne?

Das Schreiben in eine Datei kann ich ja, wie du geschrieben hast nicht mehr direkt machen, da sonst die Reihenfolge nicht stimmt. Kann ich also alles in eine Liste packen und am Ende die Liste sortieren, oder packen das 4GB Arbeitsspeicher nicht?
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

@nooby:
Die Prozesserzeugung kannst Du wohl in den Skat drücken, d.h. wenn Dein Problem gut parallelisierbar ist, macht es zunächst keinen großen Unterschied, ob ein Kern genau eine große Aufgabe erhält oder viele kleine nacheinander abarbeitet. Wenn Du Dir allerdings hierüber Gedanken machst, solltest Du vllt. vorher die Sache algorithmisch optimieren. Dabei wirst Du feststellen, dass Primzahlberechnung nicht gut parallelsierbar ist, da folgende Berechnungen auf vorherige angewiesen sind.
nooby
User
Beiträge: 91
Registriert: Montag 12. März 2012, 20:39
Wohnort: 127.0.0.1

Tut mir leid, ich kann dir nicht ganz folgen. Inwiefern ist jede Berechnung von der vorhergehenden Abhängig?
Ich versuche ja nicht, eine einzelne Zahl auf mehreren kernen zu prüfen, sondern parallel auf verschiedenen Kernen verschiedene Zahlen zu prüfen.
BlackJack

@jerch: Ich glaube im ersten Satz fehlt irgendwo ein ”nicht”. :-)

@nooby: Dein Algorithmus ist auch, äh sagen wir mal, suboptimal. Normalerweise bauen die Tests nämlich auf den bereits gefundenen Primzahlen auf. Die Zeit in eine Sieb-Lösung wäre sicher besser investiert als Deinen ineffizienten Algorithmus zu parallelisieren.
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

@nooby:
Ja, das ist richtig. Mit Deiner Vorgehensweise ist die Sache gut parallelisierbar. Allerdings ist Dein Primzahltest denkbar ineffizient und wird schnell zum Rechengau für größere Zahlenbereiche. Daher meine Anspielung auf den Algorithmus - hier gibt es noch Potential. Das kannst Du relativ einfach rausfinden, wenn Du Dir mal mit Zettel und Stift die Zahlen von 1-20 aufschreibst und anschaust, wie sich die Primzahlen ergeben (Tipp: Sieb des Eratosthenes bzw. verbesserte Versionen davon).

Ah zu langsam :)

@BlackJack: Da fehlt ein nicht? :shock:
BlackJack

@jerch: Hm, irgendwie finde ich die Aussage komisch‽ Mal davon abgesehen dass der Algorithmus an sich nicht so dolle ist, lässt der sich doch gut parallisieren und damit macht es schon einen Unterschied ob man einen Prozessor(kern) mit der ganzen Aufgabe beschäftigt, oder mehrere parallel Teilbereiche filtern lässt.
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

@BlackJack: Naja ich drück mich manchmal verklausuliert aus. Eigentlich wollte ich genau das sagen damit :oops:

Ah - jetzt versteh ich das Missverständnis. Ich meinte - es macht kaum einen Unterschied, ob man die Prozessanzahl genau auf die Kernanzahl anpasst oder den einzelnen Kern mit mehreren Aufgaben beschäftigt (mehr Prozesse als Kerne). Das gilt natürlich nicht für beliebige Zerstückelung, da Kommunikation und Zusammenführen der Daten dann sehr aufwändig werden. Aber für die Frage, ob 4 Prozesse passend zu 4 Kernen oder 8 ins Blaue geschossen, ist dieser Aufwand + Prozessgenerierung eher unerheblich.
nooby
User
Beiträge: 91
Registriert: Montag 12. März 2012, 20:39
Wohnort: 127.0.0.1

Ich habe nun das ganze mit dem Sieb des Eratosthenes programmiert. Das lief auch ganz gut, aber wenn wieder gestartet wurde, begann es immer von vorne.
Und ausserdem ist mein Algorithmus fürn Arsch. Er benötigt für alle Zahlen von 1-1000 3 Sekunden. Das ist ja sau langsam:D

Code: Alles auswählen

from datetime import datetime as DateTime
class Eratosthenes():
    def __init__(self, filename):
        self.sieb = []
        self.start = 2
        self.ende = 0
        self.filename = filename
        self.bereits_berechnet()
        self.calculate()
        self.save_primes()
    def calculate(self):
        for x in self.sieb:
            not_primes = []
            for y in range(self.sieb.index(x), len(self.sieb)):
                vielfache = x * self.sieb[y]
                if vielfache <= self.ende:
                    not_primes.append(vielfache)
            for i in not_primes:
                self.sieb.remove(i)
    def save_primes(self):
        with open(self.filename, "a") as prime_file:
            for i in self.sieb:
                prime_file.write(str(i) + "\n")
                prime_file.flush()
    def bereits_berechnet(self):
        result = 2
        try:
            with open(self.filename) as lines:
                for result in lines:
                    pass
            self.start = int(result)
            self.sieb = list(range(self.start, self.ende+1))
        except EnvironmentError:
            self.start = 2
        print('Es wurde bereits bis {0} berechnet.'.format(self.start))
        ende = int(input('Bitte gib ein, wie weit du berechnen möchtest: '))
        self.ende = ende
        self.sieb = list(range(self.start, self.ende+1))
        print(self.sieb)
if __name__ == "__main__":
    start_time = DateTime.now()
    Eratosthenes("test.txt")
    used_time = DateTime.now() - start_time
    print(
        'Super. Es wurden alle Zahlen geprüft.'
        ' Dafür hat dein Computer {0} gebraucht.'.format(used_time)
    )

Könnt ihr mir noch Mals helfen? :oops:

//Edit: Diesen Fehler habe ich gefunden. Lag daran, dass ich das Ende noch nicht eingelesen habe, als die Liste erzeugt wurde. Code erneuert (oben). Wenn ich aber bei einer bereits angefangenen Datei weiter machen möchte, schreibt er einach alle Zahlen in die Datei und ich weiss einfach nicht warum.
Antworten