Skocz do…
Zachęcony wpisem GiMa postanowiłem pobawić się w Google Treasure Hunt. Z początku moje wrażenia były negatywne, ale to dlatego, że zacząłem od zadania sieci, które jest co najmniej denne. Archiwum też nie napawało optymizmem, już zacząłem się zastanawiać, czy wszystkie będą tak prymitywne – na szczęście nie były.
Robot – kolejne zadanie, za które sie wziąłem – przypomniał mi stare dobre czasy, gdy to na lekcjach rachunku prawdopodobieństwa z umiłowaniem wyliczaliśmy na ile sposób można dojść z jednego rogu do drugiego albo ile jest n elementowych ciągów o wyrazach naturalnych, których suma wynosi m.
Na stworzenie tego wpisu zdecydowałem się jednak nie po to, aby się chwalić jaki to jestem mądry. Sprowokowało mnie do tego rozwiązanie czwartego zadania, w którym GiM wydawał się sugerować jakoby język D był niezmiernie szybki. Cóż… niechaj mój pomiar mówi sam za siebie (program napisany w C, procesor Sempron 2500+ 1,4GHz):
$ time ./sieve 20000000
max = 20000000
sequence = { 799, 415, 63, 31 }
count = 1270607
largest = 19999999
6814289
real 0m0.916s
user 0m0.817s
sys 0m0.077s
Jak widać na wolniejszym komputerze program znalazł przeszło 3 razy więcej liczb pierwszych w czasie krótszym od programu GiMa.
Teraz tylko zachodzę w głowę o co biega z tą koszulką, co to GiM ją niby dostał… ;)
A jakbyś to jeszcze w aśmie napisał... ;)
Nie dajcie sie oszukać, Java, Python i D nie będą szybsze od przemyślanego C nigdy ;)
Paradoksalnie program napisany w assemblerze mógłby działać wolniej z tej prostej przyczyny, że nie udałoby się tak dobrze dobrać rejestrów tudzież nie znam wielu technik optymalizacji, z których korzysta kompilator.
Jeśli chodzi o Javę, to ponoć w pewnych specyficznych warunkach może być szybsza od skompilowanego programu — osobiście nie za bardzo w to wierzę (podejrzewam, że jeżeli taki wynik komuś udało się uzyskać to zapewne były to całkiem teoretyczne pomiary oderwane od rzeczywistości). Teoria za tym stojąca jest taka, że program może być modyfikowany w trakcie działania co pozwala optymalizować skoki itp.
Python jako interpretowany język skryptowy z dynamicznymi typami ma faktycznie niewielkie szanse być szybszy od programów skompilowanych, ale też nie o to w nim do chodzi.
Ale jeśli już mowa o D, to może on dorównywać innym językom (GC może coś komplikować co prawda), ale mam wrażenie, iż jego kompilator zwyczajnie nie jest w stanie zoptymalizować kod tak dobrze jak kompilatory C/C++ i mam pewne wątpliwości czy będzie kiedykolwiek umiał, bo jednak język D to margines i mało osób zajmuje się ulepszaniem kompilatora tego języka.
Nie ma wątpliwości, że to co zabiera większość czasu to wygenerowanie sita.
Zwróć uwagę, że w statycznym konstruktorze jest byle-jak
napisana pętla for z użytym ~= co raczej sporo spowalnia wykonanie. Pętle tę można prosto poprawić, a szybki test mówi mi, że przyśpieszenie jest wówczas prawie 3-krotne.
Nie zmienia to faktu, że i tak wygenerowanie tablicy wielkości jak twoja, zajmuje mu prawie 2x więcej.
[jeśli rozumiem 2.000.000 elementów]
Przydałoby się sprawdzić z użyciem gdc, bo często ma lepsze optymalizacje, ale nie mam pod ręką.
Ważniejszą rzeczą natomiast jest to, ile zajęłoby Ci napisanie tego nie mając pierwowzoru :)
Bo zdaje się, że w treasure-huncie brali pod uwagę czas pomiędzy opublikowaniem zadania a nadesłaniem odpowiedzi :)
Pewnie, że mógłbym to napisać w C i pewnie nawet napisałbym szybciej niż to co napisałem w D, ale chciałem ‘poćwiczyć’, poza tym porównać jak się ma BitArray z tango do boola.
[Wszystko to to i tak nic w porównaniu z rozwiązaniem znajomego w Haskellu, które jest dosłownie zapisaniem postawionego problemu, mieści się w jakichś 10 linijkach, oczywiście nie ma sensu mówić tu o czasie wykonania, skoro czas napisania (tego w Haskellu) był nieporównywalnie krótszy :>]
Zależy jak na sprawę patrzeć. W kontekście GTH zapewne, to czy będzie liczyć pół sekundy czy pięć sekund dużego znaczenia nie ma, ale w ogólności takie różnice są istotne — wyobraź sobie co byś zrobił, gdyby Twój telefon komórkowy włączał się minutę (ostatnio coś podobnego analizowałem w pracy).
Tak czy owak, pozwoliłem sobie w ten zakamuflowany sposób wyrazić moją opinię, iż język D nie ma przyszłości. ;)
(Gwoli wyjaśnienia: mój program szukał liczb pierwszych mniejszych lub równych 20 mln i znalazł ich ponad milion).
(Komentarz zmodyfikowany 02.08.2009 o 13:03)
Uch, ciut za dużo generowałem, po poprawce, generowanie w D zabiera trochę ponad sekundę (używając dmd, gdc nie mam pod ręką nadal).
Programuję na co dzień w C, ale zysk jaki daje w tym przypadku nie jest dla mnie zbyt wymierny…
A czy ma przyszłość, cóż czas pokaże. ;)
Jeszcze małe btw: OIMW, na chwilę obecną rozwijane są 3 (albo 4 (status tego 4. jest mi nieznany)) kompilatory D.
Hmm… Może faktycznie przesadziłem. Skoro jest moduł do GCC, to może rzeczywiście idzie to jakoś optymalizować. ;)
Nadal uważam jednak, że język nie ma świetlanej przyszłości — C++ (pomimo odczapowych szablonów) już się dobrze zadomowiło i trudno, żeby nagle miliardy linii kodu przerabiać na D, a tysiące programistów wysyłać na szkolenia. Gdyby D był rozszerzeniem na C++ to mogłoby być lepiej, ale takie rozwiązanie miałoby inne wady.
Zresztą patrząc na C++0x C++ idzie w dobrym kierunku (co prawda niektóre aspekty nowego standardu mnie się nie podobają) i powodów przejścia na D może być coraz mniej, szczególnie, że jak czytam opis na wiki to wygląda na to, że D wcale nie jest pozbawiony wad. ;)
Ja czekam, kiedy D 2.x bo jak dla mnie C++0x to próba dogonienia D 1.x i Javy ;)
Nie namwiam nikogo do przerabiania kodu na D, przepisywanie kodu z języka na język z reguły jest pozbawione sensu (pomijam to, że często jest to koszmarna kalka, którą w innym języku dałoby się/powinno się zrobić lepiej/inaczej).
Co do wad, to zależy, które masz na myśli.
O nie… C++ nie musi nikogo gonić. Ma wiele mechanizmów, których programiści Javy mogą tylko pozazdrościć. Z pobierznej analizy D odniosłem wrażenie, że jedyne co ten język oferuje to łatwiejsze metaprogramowanie, a poza tym to czysty „syntetic sugar”. Z wad, jak czytam w wikipedii, mam na myślni niemożność zwracania referencji oraz dziwne zasady stałości (to drugie ma się ponoć zmienić w D 2.0).
No problemy z const to były/są przy pracach na D 2.x, ale standard D 2.x jest jeszcze nieustalony, więc nie wiadomo co to będzie.
Co do tych referencji, dla mnie to nie jest jakiś problem, tym bardziej, że już w tej chwili linia 2.x ma obsługę domknięć, których raczej w C++ próżno oczekiwać.
Co do opisanego na wiki opIndexAssign, to akurat mi się podoba, bo wymusza pisanie blah+=1; ;)
Oczywiście miłoby było, gdyby dało się używać przeciążonych operatorów typu zwróconej referencji, ale do tej pory nie było mi to jakoś specjalnie potrzebne.
Co do syntactic sugar – TAK! Ten syntactic sugar sprawia, że pisze mi się łatwiej, szybciej i przyjemniej (mówię całkiem poważnie).
Druga sprawa, że syntaktyka jest tak pomyślana, żeby usprawnić działanie kompilatora języka, dzięki czemu projekt (nie mówię tu o hello world) przerobiony z C++ na D kompiluje się nawet 10x szybciej (wystarczy się przegrzebać przez grupy digitalmarsowe, oidp conajmniej kilka osób opisywało takie doświadczenia, zresztą ja mam podobne).
(Jeszcze btw, kompilacja projektów w C++ to koszmar, kawę nie tylko zdążę zrobić ale i wypić, ale zrzucam to na to, że C++ niestety odziedziczył takie cudowne rzeczy jak #include i cały preprocesor ;/).
(Komentarz zmodyfikowany 18.01.2009 o 17:10)
W poprzednim moim wpisie pisałem o Google Treasure Hunt, a w szczególności o zadaniu czwartym. Teraz, w ramach przygotowań do kolokwium z języka Prolog postanowiłem napisać w nim rozwiązanie postawionego problemu.