Dlaczego nie ma kompilatora Pythona do natywnego kodu maszynowego?

25

Jak rozumiem, przyczyną różnicy prędkości między skompilowanymi językami a pythonem jest to, że pierwszy kompiluje kod aż do kodu natywnej maszyny, podczas gdy python kompiluje się do kodu bajtowego python, który ma być interpretowany przez PVM. Widzę, że w ten sposób kody Pythona mogą być używane na wielu systemach operacyjnych (przynajmniej w większości przypadków), ale nie rozumiem, dlaczego nie ma dodatkowego (i opcjonalnego) kompilatora dla Pythona, który kompiluje się w taki sam sposób jak tradycyjne kompilatory . Pozostawiłoby to programistom wybór, co jest dla nich ważniejsze; wykonywalność lub wydajność wieloplatformowa na maszynie macierzystej. Ogólnie; dlaczego nie ma języków, które można by traktować zarówno jako skompilowane, jak i interpretowane?

użytkownik2986898
źródło
4
Tam jest . Haskell może również zachowywać się jak skompilowany lub interpretowany przez GHCI
toasted_flakes
C ++ ma również tłumaczy . I prawdopodobnie mnóstwo innych języków ma obie implementacje.
Claudio
2
Faktycznie, wybierając IronPythong ( ironpython.net ) i skompilować kod IL wyprodukowany przy użyciu „NGEN” ( msdn.microsoft.com/de-de/library/6t9t5wcf%28v=vs.110%29.aspx ) nie jest sposobem kompilować Pythona do natywnego kodu maszynowego. Nie, żebym przetestował ten łańcuch narzędzi.
Doc Brown,
10
Można pisać kompilatory Pythona na rodzime. Po prostu nie są bardzo interesujące, ponieważ w rzeczywistości nie poprawiają wydajności o znaczący margines, chyba że faktycznie implementują język, który wygląda jak Python, ale jest znacznie bardziej ograniczony. I wcześniej opisanymi dlaczego.

Odpowiedzi:

29

Nie. Powodem różnic prędkości między językami takimi jak Python i C ++ jest to, że języki o typie statycznym dają kompilatorowi mnóstwo informacji o strukturze programu i jego danych, co pozwala mu zoptymalizować obliczenia i dostęp do pamięci. Ponieważ C ++ wie, że zmienna jest typu int, może określić optymalny sposób manipulowania tą zmienną nawet przed uruchomieniem programu. Z drugiej strony w Pythonie środowisko wykonawcze nie wie, jaka wartość jest w zmiennej, dopóki interpreter nie osiągnie linii. Jest to niezwykle ważne w przypadku struktur, w których w C ++ kompilator może łatwo określić rozmiar struktury i każde położenie swoich pól w pamięci podczas kompilacji. Daje to ogromną moc przewidywania, w jaki sposób dane mogą zostać wykorzystane, i pozwala na optymalizację zgodnie z tymi przewidywaniami.

Aby skutecznie kompilować języki takie jak Python, musisz:

  1. Upewnij się, że struktura danych jest statyczna podczas wykonywania programu. Jest to problematyczne, ponieważ Python ma eval i metaklasy. Oba, które umożliwiają zmianę struktury programu na podstawie danych wejściowych programu. Jest to jedna z rzeczy, które dają Pythonowi taką ekspresyjną moc.
  2. Wnioskuj o typach wszystkich zmiennych, struktur i klas z samego kodu źródłowego. Chociaż do pewnego stopnia jest to możliwe, system i algorytm typu statycznego byłyby tak złożone, że praktycznie niemożliwe byłoby wdrożenie go w użyteczny sposób. Możesz to zrobić dla podzbioru języka, ale zdecydowanie nie dla całego zestawu funkcji językowych.
Euforyk
źródło
6
Warto zauważyć, że czyni to problem trudnym , ale nie niemożliwym. sbcl kompiluje Common Lisp, który również jest dynamiczny, ma evali wiele innych rzeczy, aby zasmucić pisarzy kompilatorów. Nie jest na poziomie gcc, ale z pewnością jest szybszy niż interpreter CPython.
Daniel Gratzer
3
@ jozefg Powiedziałem skutecznie kompilować. Nie tylko kompiluj. Python również ma kompilator Cython, który wytwarza kod macierzysty. Chodzi o to, że kompilatory nie dokonują nawet ułamka optymalizacji, jaką mogą kompilatory dla języków o typie statycznym. A kiedy porównujesz wydajność, porównaj ją ze skompilowanym C ++ i nie interpretowanym Pythonem.
Euforia
2
Właściwie byłbyś zaskoczony, co może zrobić sbcl. Ta gra porównawcza pokazuje, że działa tak szybko jak Java, prawie tak szybko jak GHC i w zakresie od 1 do 10 razy C. Nie jest wolny jak na standardy. Tak, typy dynamiczne w pewnym stopniu hamują kompilację, ale nie tak bardzo, jak się wydaje.
Daniel Gratzer
3
Porównywanie prędkości interpretowanego Pythona do skompilowanego Pythona jest samo w sobie interesujące. Przestań mówić „użyj C ++”. Być może masz już kod napisany w Pythonie. Być może kod łatwiej jest napisać w pythonie. Kogo to obchodzi. To, na czym mi zależy, to 1,5-krotne przyspieszenie (cokolwiek to jest). To może mieć ogromną różnicę.
Thomas Eding
3
Innymi słowy, jeśli chcesz skompilować, wybierz inny dostosowany do tego język, na przykład C ++ lub Pascal.
Please_Dont_Bully_Me_SO_Lords
0

Dwie koncepcje mogą pomóc nam lepiej zrozumieć, dlaczego Python skompilowany do natywnego kodu maszynowego „może” nie działać tak szybko, jak skompilowane C lub inne powszechnie kompilowane języki. Nazywa się je wczesnym wiązaniem i późnym wiązaniem.

Powinienem zacząć od stwierdzenia, że ​​nie jestem ekspertem od Pythona i do tej witryny trafiłem przypadkiem. Ale podoba mi się ta strona.

Jak wspomniano w innej odpowiedzi tutaj, kompilator C ++ może dużo wiedzieć o programie i podejmować decyzje, których operacji użyć dla określonych struktur danych. Na przykład, jeśli należy dodać dwie zmienne całkowite, kompilator wie, że są to liczby całkowite natywne, na przykład o szerokości 32 bitów, i może je dodać razem z jedną instrukcją „DODAJ”. Więc kompiluje instrukcję ADD w kodzie. Jest zablokowany i nie można go zmienić podczas działania programu. To jest wczesne wiązanie.

Z drugiej strony w języku takim jak Python moglibyśmy oczekiwać, że program zrzuci różne typy danych w złożony sposób. Teraz kompilator nie wie, czy nasze 2 zmienne to liczby całkowite, zmiennoprzecinkowe, ciągi lub listy. Musi więc skompilować kod, który określa te informacje w czasie wykonywania i wybrać prawidłową operację podczas działania programu. To jest późne wiązanie i możemy zrozumieć, że wystąpi uderzenie w wydajności za wykonanie tej dodatkowej pracy podczas działania programu. Jest to cena, jaką płacisz za utrzymanie tych opcji w języku takim jak Python, ale zapewnia maksymalną elastyczność w czasie wykonywania.

użytkownik214354
źródło
-4

Myślę, że ma to więcej wspólnego ze specyfiką Pythona, z tego samego powodu, dla którego nie można skompilować C # do kodu maszynowego. Specyfika języka sprawiłaby, że twoje programy byłyby wadliwe, nawet gdyby było to możliwe ze względu na naturę języka. Dlaczego nie po prostu nauczyć się języka C. Jest znacznie łatwiejszy niż C ++ i nieco zaawansowany niż Python, ale wciąż dostępny.

Żwawy
źródło
5
C # może przejść bezpośrednio do kodu maszynowego: wspólny język średniozaawansowany: Kompilacja z wyprzedzeniem - „Środowiska wykonawcze kompatybilne z CLI również oferują opcję kompilacji z wyprzedzeniem (AOT) zestawu, aby przyspieszyć jego wykonanie poprzez usunięcie proces JIT w czasie wykonywania. W .NET Framework znajduje się specjalne narzędzie o nazwie Native Image Generator (NGEN), które wykonuje AOT. W Mono istnieje również opcja wykonania AOT. ”