Prędkość Javy

Prędkość Javy
BO
  • Rejestracja:prawie 10 lat
  • Ostatnio:ponad 5 lat
  • Postów:80
1

Zrobiłem test na Intel I3 3.6 GHz, milion układów 4-tego stopnia w C++ release, poza środowiskiem, C# i w Javie.
C++ 5.99 s
C++ tryb 64 bity 4.91 s.
C# - 5.12
Java chyba nie ma ustawień czy debug czy release, ale czas wołania dla jar - 2.64 s!
Z czego wynika ten świetny czas Javy? przydzielanie pamięci - w C++ operowałem na stosie. Obliczenia zmiennopozycyjne - wykorzystywałem tę samą bibliotekę dla Complex, ten sam algorytm liczb pseudolosowych, a obliczenia najbardziej zależą od koprocesora. Był jeden wątek.
Czyżby Java najbardziej do obliczeń numerycznych? Szkoda że w Javie nie ma przeciążania operatorów, przez co komplikuje się zapis liczb zespolonych, wektorów i macierzy.github

edytowany 3x, ostatnio: Borneq
nie100sowny
  • Rejestracja:prawie 9 lat
  • Ostatnio:około godziny
  • Lokalizacja:Kraków
  • Postów:402
0

Po pierwsze. Java może pre alokować coś co C++ prosi od systemu za każdym razem. Głównie pamięć.
Po drugie. Java posiada Just In Time compiler, który podczas działania programu na bieżąco go optymalizuje. (Sprawdza, które ify są zawsze prawdziwe i można je wywalić itp)
Po trzecie. Czy mierzysz czas obliczeń, czy również wczytywania programu? Jeżeli to drugie, czy użyłeś JDK9 i projektu modułów Jigsaw? Powinno to jeszcze bardziej skrócić czas ładowania programu.

Czy program w C++ był skompilowany z flagami optymalizacji np. -o3 ?

EDIT1: Brak przeciążania operatorów nic nie komplikuje, a tylko upraszcza. Przeciążając operatory można sobie zrobić ziaziu.


"Gdy się nie wie, co się robi, to się dzieją takie rzeczy, że się nie wie, co się dzieje"
edytowany 4x, ostatnio: nie100sowny
Grzyboo
Co takiego złego jest w przeciążaniu operatorów?
Wibowit
  • Rejestracja:prawie 20 lat
  • Ostatnio:minuta
0

A może masz np procesor z instrukcjami AVX i Java z nich chętnie korzysta, a reszta kompilatorów jest bardziej powściągliwa? Java zawsze próbuje JITować z użyciem wszystkich dostępnych instrukcji, bo i tak natywnego kodu po JITu nie wykorzystasz na innej maszynie.

Chociaż z drugiej strony:

Obliczenia zmiennopozycyjne - wykorzystywałem tę samą bibliotekę dla Complex, ten sam algorytm liczb pseudolosowych, a obliczenia najbardziej zależą od koprocesora.

Tę samą bibliotekę we wszystkich językach? Przecież jak miałoby to iść przez JNI to wydajność w Javie byłaby kiepska. Pokaż kod najlepiej.


"Programs must be written for people to read, and only incidentally for machines to execute." - Abelson & Sussman, SICP, preface to the first edition
"Ci, co najbardziej pragną planować życie społeczne, gdyby im na to pozwolić, staliby się w najwyższym stopniu niebezpieczni i nietolerancyjni wobec planów życiowych innych ludzi. Często, tchnącego dobrocią i oddanego jakiejś sprawie idealistę, dzieli od fanatyka tylko mały krok."
Demokracja jest fajna, dopóki wygrywa twoja ulubiona partia.
edytowany 1x, ostatnio: Wibowit
jarekr000000
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 3 godziny
  • Lokalizacja:U krasnoludów - pod górą
  • Postów:4707
1

Pokaż benchmark, a powiem Ci co zepsułeś.
Pewnie trafiłeś na Dead Code Elimination.


jeden i pół terabajta powinno wystarczyć każdemu
edytowany 2x, ostatnio: jarekr000000
BO
  • Rejestracja:prawie 10 lat
  • Ostatnio:ponad 5 lat
  • Postów:80
0

Nie patrzyłem na optymalizację o3, mierzę czas wykonania wewnątrz programu, bez wczytywania.Ta sama biblioteka do Complex z org.apache.commons.math3 , przerobiona, nie korzysta z FastMath, ale prędkość taka sama. Przetłumaczona na C++ z C# z użyciem przeciążania operatorów, zdaje się jest dokładniejsza niż ta dostarczana z C#. Program na githubie, link dodałem w pierwszym poście.

jarekr000000
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 3 godziny
  • Lokalizacja:U krasnoludów - pod górą
  • Postów:4707
0
  1. Trzeba by porównać dokładnie wyniki. Może masz jakiś błąd.
  2. Jednak w Javie przypadkiem nie trafiasz na dead code elimination - czyli w sumie Java naprawde coś liczy (openjdk) i nie widzę, żeby coś sie eliminowało.
  3. Ale czas jaki mierzysz jest totalnie nie fair wobec javy - mierzysz czas kompilacji. Przy tak, krótkich czasach ma to wpływ.
    Żeby zobaczyć jak bardzo odpal w main 2 razy
Kopiuj
test4random();
test4random();
  1. Próbowałem skompilowac C++ na g++ ale jakaś masakra w ilości błędów. -std=c++11 nie pomogło
  2. @Wibowit używa ostro SSE
Kopiuj

  0x00007f3c111e3cbd: vmulsd %xmm5,%xmm1,%xmm0
  0x00007f3c111e3cc1: vmulsd %xmm4,%xmm1,%xmm3
  0x00007f3c111e3cc5: vmulsd %xmm4,%xmm2,%xmm4
  0x00007f3c111e3cc9: vmulsd %xmm5,%xmm2,%xmm5
  0x00007f3c111e3ccd: vsubsd %xmm0,%xmm4,%xmm4
  0x00007f3c111e3cd1: vaddsd %xmm5,%xmm3,%xmm3  ;*ifne
                                                ; - util.Complex::multiply@25 (line 406)
                                                ; - polyRoots.Poly3::solve@96 (line 74)

ale pewnie po zbadaniu by wyszło, że jak zwykle niezbyt optymalnie.


jeden i pół terabajta powinno wystarczyć każdemu
edytowany 3x, ostatnio: jarekr000000
vpiotr
  • Rejestracja:ponad 13 lat
  • Ostatnio:prawie 3 lata
2

W klasie Complex:

  • nie używasz const za listą parametrów
  • żaden parametr nie jest w wersji const
  • żaden operator nie zwraca referencji
  • nie masz wersji &&

Opcja -O3 jest niezbędna przy benchmarku, chyba że go akurat debugujesz - to nie.

http://en.cppreference.com/w/cpp/language/copy_assignment
http://en.cppreference.com/w/cpp/language/operators

W aktualnej wersji żeby to zobrazować powiedziałbym że porównujesz C++ na Raspberry Pi i Jave na Xeonie.

Edit: tutaj na końcu masz podane opcje kompilatora C++ które warto stosować przy benchmarkowaniu:
https://benchmarksgame.alioth.debian.org/u64q/program.php?test=regexredux&lang=gpp&id=4

edytowany 2x, ostatnio: vpiotr
jarekr000000
Gdzie te czasy kiedy benchmark to był zoptymalizowany C ze wstawkami asm, porównywany z jvm, w ktorym wiekszość czasu szła na start maszyny i początkowe wykonywanie kodu w trybie interpretacji. Tu udało się zrypać wszystkie platformy.
jarekr000000
Co masz na myśli przez && , bo nie widze. Ok. Już widze C++11, niestety nie mam doświadzczenia w nowinkach 😀
YA
  • Rejestracja:prawie 10 lat
  • Ostatnio:dzień
  • Postów:2370
0

A jakie są czasy z pustym solve() ? Czy przypadkiem te generatory nie zjadają większości czasu, a nie samo rozwiązanie :-)

KP
  • Rejestracja:około 7 lat
  • Ostatnio:ponad 6 lat
0

https://bulldogjob.pl/news/232-ktory-jezyk-programowania-jest-najszybszy - są przypadki, gdzie Java jest szybsza niż C++.

BO
  • Rejestracja:prawie 10 lat
  • Ostatnio:ponad 5 lat
  • Postów:80
0

Wrzuciłem poprawki, aby kompilowało się z GCC wraz z projektem CodeBlocks, dodałem const za nazwami funkcji. Generatory MT zabierają mniej niż 10% całości.

edytowany 1x, ostatnio: Borneq
vpiotr
Nie zapomnij o referencjach w wyniku (nie zawsze!). Patrz linki które dodałem do mojego postu.
jarekr000000
teraz wychodzi mi mniej wiecej g++ z optymalizacjami 1.2 sekundy - java 1.55 sekundy. W tego typu benchmarkach dość typowy wynik. (sorry były zmiany - bo zauważylem, że troche zmeieniałem kod)
ZA
  • Rejestracja:prawie 8 lat
  • Ostatnio:ponad 3 lata
  • Lokalizacja:Warszawa
  • Postów:87
0

Moje czasy:
C++: 1.993682 2.073570 2.037815 2.001485 2.077999 1.989976 2.072519
Java: 3.495080346 3.090479274 2.63704866 3.189946434 3.143792008 3.153356039 2.783030576
Ubuntu 16.04 na x86-64, g++ 5.4.0, Oracle JDK 8u162, .opcje g++: g++ -Wall -O3 -o bench *.cpp, opcje javy java -server polyRoots.Main,


Rust Evangelization Strike Force
Zobacz pozostałe 3 komentarze
ZA
2.400 to on ma w idle, pewnie się rozpędza przy obciążeniu
czysteskarpety
czysteskarpety
dobry cep jak na gen.3 i chłodny
ZA
@czysteskarpety: true, ThinkPad W530, z 16GB RAM, SSD i HDD, w dodatku używany, więc był tani, a bateria dalej dobra.
jarekr000000
@Wibowit - u mnie to nie ma sensu - odpalam na VMWare (i to teraz na osazczedzaniu baterii) - tak więc tylko porównanie vs C++ ma sens. (normalnie tam jakiś i6820HK 2.7ghz siedzi )
R3id4k
W idle ten procek ma 1200 tak jak w moim ThinkPad, a rozpędza się do 3.3 i trzyma. Maks 3.4 na jednym wątku ale to przebłysk pod Windows 10.
jarekr000000
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 3 godziny
  • Lokalizacja:U krasnoludów - pod górą
  • Postów:4707
0

Ciekawe jest porównanie różnych wersji JVM: (odpalałem w pętli 10 powtórzeń i bralem ostatnie wyniki. -Xms4g -Xmx4g tak for fun).

Kopiuj
java version "1.8.0_112"
Java(TM) SE Runtime Environment (build 1.8.0_112-b15)
Java HotSpot(TM) 64-Bit Server VM (build 25.112-b15, mixed mode)

czas ~= 1.28s
Kopiuj
java version "9.0.1"
Java(TM) SE Runtime Environment (build 9.0.1+11)
Java HotSpot(TM) 64-Bit Server VM (build 9.0.1+11, mixed mode)

czas~= 1.18s
Kopiuj
java version "10" 2018-03-20
Java(TM) SE Runtime Environment 18.3 (build 10+46)
Java HotSpot(TM) 64-Bit Server VM 18.3 (build 10+46, mixed mode)

czas ~= 1.143s

a C++ ( niestety g++ pod cygwin).

Kopiuj
g++ (GCC) 6.4.0
Copyright (C) 2017 Free Software Foundation, Inc.
g++ -O3 -fomit-frame-pointer -march=native  -std=c++17 -fopenmp -flto -I . *.cpp

czas ~= 0.94s 

Nadal nie mam pewności czy oba C++ i Java to samo faktycznie mierzą (precyzja, rozkład losowy itp.).

Jak sam robie taki benchmark to zrzucam sprawdzam ileś tam próbek na dysk i porównuje czy double są te dokładnie same. Inaczej to mocno może być niepewne- (btw. to jest np. ważny punkt przy testowaniu CPU vs GPU - często wychodzi, że jak się chce mieć taką dokładnie samą precyzję jak na CPU to wyniki nie są już różowe, przy pewnych symulacjach zgodność z IEEE nie ma znaczenia, ale przy pewnych ma kolosalne).


jeden i pół terabajta powinno wystarczyć każdemu
edytowany 5x, ostatnio: jarekr000000
vpiotr
  • Rejestracja:ponad 13 lat
  • Ostatnio:prawie 3 lata
0

Projekt w Code::Blocks otworzył się bez problemu. W Eclipsie - nie bardzo.
Napisałem więc skrypty do Javy:

Kopiuj
# build.sh
rm -rf ./target
mkdir ./target
javac -Xlint:unchecked -encoding ISO-8859-15 -d ./target ./src/**/*.java
Kopiuj
# run.sh
java -cp ./target polyRoots.Main "$@" 

Wyniki dla niezmodyfikowanych źródeł:

Java

Kopiuj
java version "1.8.0_111"
Java(TM) SE Runtime Environment (build 1.8.0_111-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.111-b14, mixed mode)

Time=2.085252045

C++

Kopiuj
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609

time=1.630913

Też jestem zdania że test powinien wyświetlać końcowy wynik.
Oprócz tego budować się z konsoli.

Po zmianie operatora przypisania w C++ na:

Kopiuj
Complex& Complex::operator=(const Complex &src)

i parametrów kompilatora na:

Kopiuj
-march=corei7 -fomit-frame-pointer -O3

wynik dla C++ to

Kopiuj
time=1.533322

Edit 2:
Po dodaniu rozgrzewania do Javy:

Kopiuj
	private static void test4random(boolean showTime) {
                //...
		if (showTime) System.out.println("Time=" + estimatedTime/1e9);
	}


	public static void main(String[] args) {
		Locale.setDefault(new Locale("en", "US"));
		int c = 10; 
		test4random(false);
		while(c-->0) 
		  test4random(true);
        }

Kopiuj
Time=1.675183037
Time=1.64695364
Time=1.69172101
Time=1.64810921
Time=1.644952009
Time=1.657532988
Time=1.695351254
Time=1.679284253
Time=1.679228825
Time=1.687269182

A po włączeniu w C++ dodatkowych opcji -flto -march=native

Kopiuj
time=1.213913
edytowany 2x, ostatnio: vpiotr
Wibowit
  • Rejestracja:prawie 20 lat
  • Ostatnio:minuta
0

No dobra, to teraz wyniki ode mnie :) Na początek oczywiście zmieniłem wersję Javową tak, by test odpalał się 10x, a nie raz, bo nie chcemy mierzyć czasu kompilacji, a stabilny czas wykonywania.

Stan z commita: 0d51188c04084021e5c6e2557848048d1ecb5c2a

Wersja C++ daje takie wyniki (kilka razy odpalona binarka):

Kopiuj
g++ (Ubuntu 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609
g++ -Wall -O3 -std=c++11 -o bench *.cpp

time=1.534404 sec.
time=1.529608 sec.
time=1.531132 sec.
time=1.531274 sec.
time=1.531969 sec.

Wersja Javowa daje takie wyniki (10x powtórzona główna metoda):

Kopiuj
java version "1.8.0_161"
odpalone z IntelliJa

Time=1.99268938
Time=1.59109558
Time=1.595345558
Time=1.595759508
Time=1.595871043
Time=1.591842441
Time=1.592763768
Time=1.605932232
Time=1.574023946
Time=1.578623908

i5-4670 @ 3.8 GHz, Ubuntu 16.04 64-bit

Różnice w wydajności C++ vs Java po rozgrzaniu JVMki są jak widać kosmetyczne.

PS:
Do mierzenia wydajności krótkich metod w Javie są specjalne narzędzia jak np http://openjdk.java.net/projects/code-tools/jmh/

Aktualizacja:
Po dodaniu -flto i -march=native sytuacja się zmienia:

Kopiuj
g++ -Wall -O3 -std=c++11 -flto -march=native -o bench *.cpp

time=1.110629 sec.
time=1.108664 sec.
time=1.110985 sec.
time=1.108843 sec.
time=1.110323 sec.
time=1.105393 sec.

Taka binarka jest jednak nieprzenośna.

PPS:
Java 9 lepiej sobie radzi z wektoryzacją niż Java 8, więc wyniki na niej powinny być lepsze. Przykład: http://prestodb.rocks/code/simd/


"Programs must be written for people to read, and only incidentally for machines to execute." - Abelson & Sussman, SICP, preface to the first edition
"Ci, co najbardziej pragną planować życie społeczne, gdyby im na to pozwolić, staliby się w najwyższym stopniu niebezpieczni i nietolerancyjni wobec planów życiowych innych ludzi. Często, tchnącego dobrocią i oddanego jakiejś sprawie idealistę, dzieli od fanatyka tylko mały krok."
Demokracja jest fajna, dopóki wygrywa twoja ulubiona partia.
edytowany 7x, ostatnio: Wibowit
Zobacz pozostałe 3 komentarze
jarekr000000
@Wibowit: sam je wkleiłem, ale nie wiem co dokładnie zrobili. W sumie nie wiem też czy to dzięki SIMD.
Wibowit
Ach sorry, dopiero wstałem :P :P :P
jarekr000000
Spoko. Ja też jeszcze śpię - tyle, że w biurze .Tu lepiej i tak umysłu nie używać.
Shalom
Ja bym sie zastanowił czy do porównania w C++ nie używać flag -D_FORTIFY_SOURCE=2 -fpie -Wl,-pie -fstack-protector-strong -Wl,-z,relro,-z,now że mieć takie samo "bezpieczeństwo" w aplikacji :P
0

Kolejny głupi wątek typu Php vs C++, Fortran vs Rust albo "czy opłaca się pisać gry na pc w php?".

Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)