Performance-Vergleich C, Java und Python

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
chrix
User
Beiträge: 1
Registriert: Dienstag 19. Mai 2015, 16:32

Hallo Zusammen,

im Versuch die Laufzeit von verschiedenen Programmiersprachen zu vergleichen hab ich versucht, Primzahlen berechnen zu lassen und die Laufzeit des Programms ausgeben zu lassen. Dabei sind mir gravierende Unterschiede aufgefallen:
Ich lasse alle Primzahlen bis 100.000 berechnen. Während C und Java alle Primzahlen innerhalb von 2-3 Sekunden berechnet haben, benötigt Python ca 240 Sekunden.

Worin liegt dieser gravierende Unterschied bzw. gibt es optimimierungen für Python?

Code: Alles auswählen

import time

def isPrime(num):
    loop = 2
    while num > loop :
        if num % loop == 0 and loop != num:
            return False
        loop += 1
    return True

maxNum = 100000
primelist = []
i = 0
end = 0
start = time.time()

for i in range(maxNum):
    if isPrime(i):
        primelist.append(i)
        
end = time.time()

for i in primelist:
    print(i)
print("Laufzeit: " + str(end - start))

Code: Alles auswählen

import java.util.ArrayList;
import java.util.List;


public class Calc {
	public static void main(String[] args) {

		int maxNum = 100000;
		List<Integer> liste = new ArrayList<Integer>();
		long end = 0;
		long start = System.nanoTime();

		for (int i = 0; i < maxNum; i++) {
			if (isPrime(i)) {
				liste.add(i);
			}
		}

		end = System.nanoTime();;
		for(int num : liste){
			System.out.println(num);
		}
		
		System.out.println("Laufzeit: " + (double)(end - start)/1000000000);

		return;
	}

	private static boolean isPrime(int num) {
		int loop = 2;
		while (num > loop) {
			if (num % loop == 0 && loop != num) {
				return false;
			}
			loop += 1;
		}
		return true;
	}
}
Benutzeravatar
darktrym
User
Beiträge: 784
Registriert: Freitag 24. April 2009, 09:26

Benutz PyPy.
„gcc finds bugs in Linux, NetBSD finds bugs in gcc.“[Michael Dexter, Systems 2008]
Bitbucket, Github
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Und dann noch mehr stellen, damit der JIT richtig in Fahrt kommt...

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

Oder vielleicht nicht so einen furchtbaren Algorithmus und vielleicht nicht gerade einen Vergleich bei dem zu erwarten ist das eine dynamische Programmiersprache wie Python einer statisch kompilierten unterlegen ist weil der aus grundlegenden Rechenoperationen mit ganze Zahlen auskommt die vom Prozessor direkt in einer engen Schleife ausgeführt werden können wenn man das zu nativem Code compilieren kann.
Benutzeravatar
darktrym
User
Beiträge: 784
Registriert: Freitag 24. April 2009, 09:26

Also, auf meinen beileibe nicht mehr aktuellen Notebook komme ich mit PyPy in die Sekundenregion(3,5s).
„gcc finds bugs in Linux, NetBSD finds bugs in gcc.“[Michael Dexter, Systems 2008]
Bitbucket, Github
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Naja, mit einem intelligenten Algorithmus schafft es Python in unter 0.005s. Da braucht schon das Kompilieren eines C oder Java Programms deutlich länger ;-)
Benutzeravatar
bwbg
User
Beiträge: 407
Registriert: Mittwoch 23. Januar 2008, 13:35

Das Verhältnis von 1:100 von statischer in Maschinencode (C, C++, Java, ...) zu einer dynamischen, interpretierten Sprache empfinde ich nicht als gravierend. 240 Sekunden mag subjektiv lang erscheinen, 2-3 Sekunden für das bisschen Rechnerei wären mir allerdings mit C und Derivaten auch zu langsam ;)

Etwas umgeschrieben braucht meine Desktop-Kiste mit CPython noch rund 10s.
"Du bist der Messias! Und ich muss es wissen, denn ich bin schon einigen gefolgt!"
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Das ganze ist ja eh praxisfern... Für number-crunching ist Python nicht gemacht.

Also was soll man eigentlich vergleichen?!?

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
darktrym
User
Beiträge: 784
Registriert: Freitag 24. April 2009, 09:26

Er will ja vermutlich die Sprache vergleichen, nicht dessen Implementierung bzw. Dauer bei der Ausführung.
Sogesehen ist der Thread sinnfrei².
„gcc finds bugs in Linux, NetBSD finds bugs in gcc.“[Michael Dexter, Systems 2008]
Bitbucket, Github
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Und wenn man's ganz genau nimmt, dann sollte man auch nicht von einem Sprachvergleich sprechen, sondern von einem Vergleich der Compiler bzw Laufzeitumgebungen. Es wurde ja schon angesprochen, dass sich Python-Programme mit PyPy deutlich performanter verhalten können als mit CPython.

Und wenn man ein bißchen mehr Praxisbezug einbaut und sich in Python z.B. Unterstützung von NumPy holt, dann kann man für umfangreiche mathematische Berechnungen meistens auch nochmal einiges an Speed rausholen.

Fakt ist, dass Python nur sehr wenig am Code optimiert und aufgrund seiner dynamischen Natur vieles tut, was Java mit seinen statischen primitiven Typen nicht tun muss. Das macht sich besonders bemerkbar, wenn man viele Schleifendurchläufe hat, weil sich die zusätzlich benötigte Zeit dann eben spürbar aufsummiert.

Wie gesagt: PyPy kann hier schon weiterhelfen, da dort u.a. durch bestimmte Annahmen und fortgeschrittene Analyseverfahren an heiklen Stellen (sogenannte Hotspots) dafür gesorgt wird, dass trotz dynamischer Typisierung vieles am Ende eben doch wie bei statischer Typisierung behandelt werden kann. Mal als Beispiel: Eine Liste von Objekten mit prinzipiell total unterschiedlichen Typen könnte wie eine Liste mit Objekten vom Typ ``int`` behandelt werden, da man eben in aller Regel zwischen 20.000 Zahlen nicht plötzlich ein String-Objekt einbaut. Solche und andere Vorkehrungen verbessern dann dementsprechend die Performance beim Ausführen des Programms.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Ich habe neulich mal etwas von Numba gelesen... evtl. kann man damit auch noch Performance rauskitzeln?
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

Hyperion hat geschrieben:Ich habe neulich mal etwas von Numba gelesen... evtl. kann man damit auch noch Performance rauskitzeln?
Ja, kann man. Aber Python wählt man ohnehin nicht, um den schnellst möglichen Maschinencode zu erhalten, sondern um schnell funktionstüchtige Programme zu erstellen. Wenn es dann zu langsam ist und sich auch algorithmisch nichts mehr verbessern lässt, kann man je nach Anforderungen zu numpy oder numba etc. greifen oder eigene C-Extensions schreiben. Aber was erzähle ich hier ... :)
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Das Wiki Thema hab ich abgetrennt. Bitte bei http://www.python-forum.de/viewtopic.php?f=10&t=36326 dazu weiter machen :wink:

Aber mein Statement passt hier dennoch: Das Thema wäre eigentlich was für einen http://wiki.python-forum.de/FAQ Eintrag... :lol:

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Ene Uran
User
Beiträge: 125
Registriert: Sonntag 17. September 2006, 20:14
Wohnort: Hollywood

Etwas zum Lachen ...

Code: Alles auswählen

import numpy as np

def np_primes1(limit):
    """
    returns a numpy array of primes, 2 <= p < limit
    """
    # create a sieve of ones
    is_prime = np.ones(limit + 1, dtype=np.bool)
    for n in range(2, int(limit**0.5 + 1.5)):
        if is_prime[n]:
            is_prime[n*n::n] = 0
    return np.nonzero(is_prime)[0][2:]

''' Resultat gemessen mit module timeit ...
np_primes1(100000) --> 0.295 milliseconds/pass
np_primes1(1000000) --> 3.107 milliseconds/pass
'''
Selbst ohne numpy ...

Code: Alles auswählen

def eras_dns(n):
    """
    returns  a list of primes 2 to < n
    """
    sieve = [True] * (n>>1)
    for x in range(3, int(n**0.5)+1, 2):
        if sieve[x>>1]:
            sieve[(x*x)>>1::x] = [False] * ((n-x*x-1)//(x<<1)+1)
    return [2] + [(x<<1)+1 for x in range(1, n>>1) if sieve[x]]

''' Resultat gemessen mit module timeit ...
eras_dns(100000)   --> 4.10 milliseconds/pass
eras_dns(1000000)  --> 41.48 milliseconds/pass
'''
Eine Variante von eras_dns(100000) in Go (Google supermodern C) braucht etwa 500 microseconds, so ist Python also immer noch etwas langsamer.

System iMac:
3.4.3 |Anaconda 2.2.0 (x86_64)| (default, Mar 6 2015, 12:07:41)
[GCC 4.2.1 (Apple Inc. build 5577)]
Atomkraftwerkaktienbesitzer
Antworten