Python und C++(C)

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.
PmanX
User
Beiträge: 123
Registriert: Donnerstag 25. Januar 2007, 13:50
Wohnort: Germany.BB.LOS
Kontaktdaten:

Hallo,

was ich absolut nicht verstehen kann ist, dass so super allgemein drum herum geredet wird. Warum gibt es kein konkretes Projekt, wofür eine Lösung gesucht wird :!: Dann eine Weg suchen zu parallelisieren.
Was spricht dagegen, wenn ein Proz die Datenbank, ein weiterer den PVR .. bedient?
In den seltensten Fällen wird nur dieses eine Pythonprogramm laufen.

Gruß P.
Benutzeravatar
nkoehring
User
Beiträge: 543
Registriert: Mittwoch 7. Februar 2007, 17:37
Wohnort: naehe Halle/Saale
Kontaktdaten:

Mal zurueck zum Thema Geschwindigkeit... ich hab mir vor... - ja ich weiß garnichtmehr - ...ein oder zwei Wochen, mal eine kleine Schleife gebaut, die die letzte Primzahl vor einer Gegebenen Zahl sucht.

Also zB gibst du die 10000 an und bekommst dann 9973 zurueck.

Und als ich hier im Thread stoeberte kam mir mal die Idee, einen Vergleich zu ziehen... die Schleife normal und mit Psyco:

(gezeigt wird immer die Ausgabe der dritten Ausfuehrung)

Code: Alles auswählen

psy@BrAIN1ak> ./letzte_primzahl.py 100000
99991 ( 0.0576159954071 secs)
psy@BrAIN1ak> ./letzte_primzahl.py 1000000
999983 ( 0.548065900803 secs)
psy@BrAIN1ak> ./letzte_primzahl.py 10000000
9999991 ( 5.59474992752 secs)
und jetzt... *trommelwirbel* 8)

Code: Alles auswählen

psy@BrAIN1ak> ./letzte_primzahl_psyco.py 100000
99991 ( 0.00420188903809 secs)
psy@BrAIN1ak> ./letzte_primzahl_psyco.py 1000000
999983 ( 0.0389289855957 secs)
psy@BrAIN1ak> ./letzte_primzahl_psyco.py 10000000
9999991 ( 0.379332065582 secs)

...ja nun bin ich wirklich sprachlos :o
Vorallem weil dieser Geschwindigkeitszuwachs durch zwei Zeilen Code entsteht. Hier der Code, fuer interessierte:

Code: Alles auswählen

#!/usr/bin/python

from sys import argv
from time import time

import psyco
psyco.full()

stop = int(argv[1])

def quer(x):
    x = [int(n) for n in list(str(x))]
    return sum(x)


def is_prim(x):
    if str(x).endswith("5"): return False
    elif int(str(x)[-1])%2 == 0: return False
    elif x>10:
        if quer(x)%3 == 0: return False

    n = 2
    while n<x:
        if x%n == 0: break
        else: n+=1
    else:
        return True
    return False

stamp = time()
while not is_prim(stop): stop -= 1
stamp=time()-stamp
print stop, '(', stamp, 'secs)'
natuerlich koennte man noch abfangen, ob Psyco ueberhaupt installiert ist usw... aber naja... es ist ja nur fuer mich, eigentlich ;)
[url=http://www.python-forum.de/post-86552.html]~ Wahnsinn ist auch nur eine andere Form der Intelligenz ~[/url]
hackerkey://v4sw6CYUShw5pr7Uck3ma3/4u7LNw2/3TXGm5l6+GSOarch/i2e6+t2b9GOen7g5RAPa2XsMr2
BlackJack

@lumax: Python benutzt die Threads vom Betriebssystem.

Ich weiss nicht ob sich das jeder der Diskutanten klar macht: Ein Programm kann nicht auf magische Weise mehrere Prozessoren/Kerne benutzen. Da muss der Programmierer immer etwas für tun. Wenn das "global interpreter lock" nicht mehr vorhanden wäre, ändert sich an allen Programmen, die keine Threads benutzen rein gar nichts.

Selbst wenn es möglich wäre, dass Python-Bytecode in mehreren Threads parallel ausgeführt wird, ist immer noch nicht garantiert, dass diese Threads auch auf mehrere Prozessoren/Kerne verteilt werden.
Benutzeravatar
nkoehring
User
Beiträge: 543
Registriert: Mittwoch 7. Februar 2007, 17:37
Wohnort: naehe Halle/Saale
Kontaktdaten:

Einfach um meinen Kopf ein wenig frei zu kriegen, nach tagelanger Programmierung an einer Sache... habe ich die Primzahlenschleife mal in C implementiert. Hier das Ergebniss:

Code: Alles auswählen

psy@BrAIN1ak> ./a.out
99991 (0 clockcycles)  # <1 secs
999983 (30000 clockcycles)  # 0.03 secs
9999991 (270000 clockcycles) # 0.27 secs
Eine Millionen Clockcycles entsprechen hier einer Sekunde. Ich hoffe das diese Art der Messung hier passt.


Und hier wieder der Code fuer Interessierte...

Code: Alles auswählen

/*
 * Gibt die letzte Primzahl vor der per Argument uebergebenen Zahl aus.
 */


#include <stdio.h>
#include <time.h>


int quer(int x)
{
    int wertigkeit, hilf, summe = 0;

    hilf=x;
    wertigkeit = 1;

    while((hilf=hilf/10) != 0) wertigkeit=wertigkeit * 10;

    do {
        summe = summe + x / wertigkeit;
        x = x % wertigkeit;
        wertigkeit = wertigkeit / 10;

    } while(wertigkeit > 0);

    return summe;
}

int is_prim(int x)
{
    int n = 2;

    if (x%5 == 0) return 0;
    if (x%2 == 0) return 0;
    if (x>10) {
        if (quer(x)%3 == 0) return 0;
    }
    
    while (n<x) {
        if (x%n == 0) return 0;
        else n++;
    }
    return 1;
}


int main()
{
    int stop;
    clock_t stamp;

    stop = 100000;
    stamp = clock();
    while (!is_prim(stop)) stop--;
    stamp = clock() - stamp;
    printf("%d (%d clockcycles)\n", stop, stamp);

    stop = 1000000;
    stamp = clock();
    while (!is_prim(stop)) stop--;
    stamp = clock() - stamp;
    printf("%d (%d clockcycles)\n", stop, stamp);

    stop = 10000000;
    stamp = clock();
    while (!is_prim(stop)) stop--;
    stamp = clock() - stamp;
    printf("%d (%d clockcycles)\n", stop, stamp);

    return 0;
}
:oops: ist der lang :shock:
[url=http://www.python-forum.de/post-86552.html]~ Wahnsinn ist auch nur eine andere Form der Intelligenz ~[/url]
hackerkey://v4sw6CYUShw5pr7Uck3ma3/4u7LNw2/3TXGm5l6+GSOarch/i2e6+t2b9GOen7g5RAPa2XsMr2
BlackJack

Das mit der Quersumme hatte irgendwie bei mir gar keinen Einfluss auf die Laufzeit. Ich hab's mal ein wenig verändert. Ist jetzt kürzer und schneller:

Code: Alles auswählen

$ ./a.out
99991 (0 clockcycles)
999983 (0 clockcycles)
9999991 (0 clockcycles)
Und der Code:

Code: Alles auswählen

#include <math.h>
#include <stdio.h>
#include <time.h>


int is_prim(int x)
{
    int n;

    if (x == 2) return 1;
    if (!(x & 1)) return 0;
    for (n = 3; n < sqrt(x); n += 2) {
        if (!(x % n)) return 0;
    }
    return 1;
}


int main()
{
    int i, stop;
    clock_t stamp;

    for (i = 0; i < 3; ++i) {
        stop = 100000 * pow(10, i);
        stamp = clock();
        while (!is_prim(stop)) stop--;
        stamp = clock() - stamp;
        printf("%d (%d clockcycles)\n", stop, (int) stamp);
    }

    return 0;
}
Benutzeravatar
nkoehring
User
Beiträge: 543
Registriert: Mittwoch 7. Februar 2007, 17:37
Wohnort: naehe Halle/Saale
Kontaktdaten:

okay.. du beherrscht C eindeutig besser als ich ^^
Ich hab allerdings auch direkt die Python-Implementierung "abgeschrieben" ...ich wollte ja nun einen Vergleich ziehen.

Aber danke dafuer... :D

EDIT: Das klappt nicht... irgendwie findet er sqrt() und pow() nicht -.-

EDIT2: Also wenn ich das hier mache:

Code: Alles auswählen

#include <stdio.h>
#include <math.h>


int main(int argc, char *argv)
{
        printf("> %f <\n", sqrt(pow(5, 2)));

        return 0;
}
...klappts... vielleicht bin ich auch zu bloed... denn bei meinem kumpel (DevC++ unter WinXP vermute ich mal) klappt dein Code auch. Ich hab uebrigens den GCC4.x unter nem normalen x86er Linuxkernel...

EDIT3 ^^ GCC4.1.1 und GCC3.4.6 habe ich jetzt getestet
[url=http://www.python-forum.de/post-86552.html]~ Wahnsinn ist auch nur eine andere Form der Intelligenz ~[/url]
hackerkey://v4sw6CYUShw5pr7Uck3ma3/4u7LNw2/3TXGm5l6+GSOarch/i2e6+t2b9GOen7g5RAPa2XsMr2
Benutzeravatar
nkoehring
User
Beiträge: 543
Registriert: Mittwoch 7. Februar 2007, 17:37
Wohnort: naehe Halle/Saale
Kontaktdaten:

wow... also egal wieso die C-Variante nicht funktionieren will... in Python (mit Psyco) ist es so dermaßen schnell, was du da gebaut hast ^^... ja ist auch klar. Du erhoehst n gleich um 2 (sinnigerweise ^^) und ueberpruefst nur bis zur Wurzel der gegebenen Zahl.

Naja.. die Python-Implementation ist jedenfalls so schnell, dass ich die letzte Primzahl unter einer Billion in 0.6 sekunden ausrechne... meine alte Variante rechnet immernoch... keine Ahnung wie lang. Ein paar Minuten sinds aber schon. :roll:

Wer die neue Pythonvariante haben mag:

Code: Alles auswählen

#!/usr/bin/python

from sys import argv
from time import time

import psyco
psyco.full()

stop = int(argv[1])

def is_prim(x):
    if x==2: return True
    if not (x & 1): return False

    n = 3
    while n < (x**0.5):
        if not x%n: return False
        n += 2

    return True

stamp = time()
while not is_prim(stop): stop -= 1
stamp=time()-stamp
print stop, '(', stamp, 'secs)'
[url=http://www.python-forum.de/post-86552.html]~ Wahnsinn ist auch nur eine andere Form der Intelligenz ~[/url]
hackerkey://v4sw6CYUShw5pr7Uck3ma3/4u7LNw2/3TXGm5l6+GSOarch/i2e6+t2b9GOen7g5RAPa2XsMr2
BlackJack

Falls sich der Linker beschwert:

Code: Alles auswählen

$ gcc -O3 -Wall -ansi -pedantic test.c
/tmp/ccGLyIIq.o: In function `is_prim':test.c:(.text+0x47): undefined reference to `sqrt'
/tmp/ccGLyIIq.o: In function `main':test.c:(.text+0xcd): undefined reference to `pow'
:test.c:(.text+0x1a1): undefined reference to `sqrt'
collect2: ld returned 1 exit status
Dann hast Du nicht gesagt, dass die Mathebibliothek mit eingebunden werden soll:

Code: Alles auswählen

$ gcc -O3 -Wall -ansi -pedantic -lm test.c
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

BlackJack hat geschrieben:Ich weiss nicht ob sich das jeder der Diskutanten klar macht: Ein Programm kann nicht auf magische Weise mehrere Prozessoren/Kerne benutzen. Da muss der Programmierer immer etwas für tun.
Da hast du wohl recht... Allerdings ist es IMHO z.Z. so, das ein Programmiere keine Möglichkeiten hat sein Programm zu parallelisieren. Der einzige Weg ist es wohl ein Python Interpreter pro Prozessor/Core zu starten.

Ich meine, ich selber werde wohl nie etwas in der Richtung machen. Ich frage mich halt aber dennoch, ob Python da nicht ein Trend verschlafen hat. Das wäre wirklich schade.
Ich meine Python wird halt recht oft, im Forschungumfeld eingesetzt. Dort ist das Thema Parallelisierung schon wichtig, denke ich. Dort könnte es vielleicht auch wichtig sein, mehr als 2GB Speicher zu benutzten, was IMHO auch nur gescheit mit 64Bit geht. Wie sieht es damit aus?

Weiß jemand eigentlich was andere Programmiersprachen in der Richtung so bieten?

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
BlackJack

Im Forschungsumfeld wird AFAIK fast immer auf Prozesse gesetzt. Das skaliert einfach besser, weil man die Berechnungen auch auf verschiedene Rechner verteilen kann. Meistens wird wohl MPI als Schnittstelle zur Kommunikation eingesetzt.

Und das man keine Möglichkeiten in Python hat, hast Du im gleichen Satz ja widerlegt: Prozesse. Mit relativ einfach zu programmierender Kommunikation beispielsweise über XML-RPC oder Pyro.

Und das GIL betrifft auch nur Python-Bytecode, dass heisst in C-Erweiterungen kann man das durchaus umgehen.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Mir ist ein Praxis Beispiel eingefallen: z.B. PIL. Bei großen Umrechungsaktionen wäre es vermutlich wohl besser, wenn dual cores genutzt werden.

Wenn ich das jetzt aber richtig verstanden hab, könnte man den PIL Teil der in C geschrieben ist, durchaus parallelisieren und für dual cores optimieren???

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
BlackJack

Ja das ginge wohl. Für Numpy wäre das eventuell auch interessant.
Benutzeravatar
nkoehring
User
Beiträge: 543
Registriert: Mittwoch 7. Februar 2007, 17:37
Wohnort: naehe Halle/Saale
Kontaktdaten:

Ach ich weiß auch nicht... dieses ganze Dual- und von mir aus auch Quadcore-Gehabe ist mir einfach nix. Ich hab natuerlich nix gegen mehrkernige Systeme, aber an sich sind doch spezialisierte Recheneinheiten viel besser. Umsonst haben wir ja keine Extra-Soundkarte und keinen Extra-Grafikchip. Im Prozessorbereich schaue ich mir bei solchen Dingen zB den Cell-Prozessor gern an. Da lohnen sich Optimierungen erstmal richtig. Aber so merkt man einen echten Unterschied doch erst bei wirklich krassen superskalierten Rechnern.

Naja... ich werd mir trotzdem wieder nen Dualcore-Ding kaufen, wenn ich mir naechsten Monat nen Rechner besorge... nur mit dem Unterschied, dass ich wenigstens ein vernuenftiges System drauf habe :-P

Aber um hier mal diesen Diskussionen Win-vs-Lin aus dem Weg zu gehen, komme ich mal zum Thema zurueck ^^

Das C-Programm ist irgendwie eklig schnell. Ich hab nun auch mal die Integer durch Long Long Ints ausgetauscht. Irgendwie hab ich jetzt nur noch Null Cycles ...auch wenn ich die Kapazitaet der Integer voll auslaste. Nun wuerde ich natuerlich gern mit groesseren Zahlen rechnen. In Python kein Problem... wie aber geht sowas in C?

EDIT: ehm... habs raus... inttypes.h rulez *hrhr*
Zuletzt geändert von nkoehring am Samstag 17. März 2007, 21:32, insgesamt 1-mal geändert.
[url=http://www.python-forum.de/post-86552.html]~ Wahnsinn ist auch nur eine andere Form der Intelligenz ~[/url]
hackerkey://v4sw6CYUShw5pr7Uck3ma3/4u7LNw2/3TXGm5l6+GSOarch/i2e6+t2b9GOen7g5RAPa2XsMr2
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Apropos GIL noch ein paar Links: GIL of Doom und Can't we get rid of the Global Interpreter Lock?. Erst letztens habe ich dazu eine Diskussion gelesen (oder eher Gedanken über mehrere Blogs verteils), aber ich kann sie leider nicht mehr finden. Ich glaube es ging darum, wie es in Python 3 gelöst sein wird.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
BlackJack

Für beliebig grosse/präzise Zahlen in C kann man zum Beispiel die GMP-Bibliothek benutzen. Eine Python-Anbindung gibt's auch.
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Bei den Debian-Paketen findet man uebrigens die beiden MPI-faehigen Python-Interpreter lampython und mpichpython. Leider spuckt Google dazu nicht viel aus... (mpichpython: Meinten Sie teppichpython? lampython: Meinten Sie baumpython? :lol:)
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Rebecca hat geschrieben:(mpichpython: Meinten Sie teppichpython? lampython: Meinten Sie baumpython? :lol:)
Das relevante ist aber das Paket python-mpi welches Teil von Scientific python ist (ganz recht, da kommt ein 404, leider), daneben gibt es noch pythonMPI (dito), pympi und pypar.

Scheinen alle etwas eingeschlafen zu sein. Aber den Quellcode zu Scientific Python kann man sich immerhin noch von Debian holen, er könnte auch mit neueren Python-Versionen funktionieren. Habe ich mir nicht so genau angesehen.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Antworten