Taková čísla obvykle stojí dost na vodě, protože záleží na tom, co počítáte a hlavně jak to naprogramujete. „V některých situacích“ je navíc extrémně vágní pojem, a vůbec bych se nedivil, kdyby v jiných „některých situacích“ byl FreeMat rychlejší než Matlab.
Nicméně, jinak mám podobnou zkušenost. Aby to nestálo na vodě, zde je konkrétní benchmark skript testující rychlost několika základních indexovacích operací s poli: http://artax.karlin.mff.cuni.cz/~hajej2am/ulozna/benchmark_index.m
Matlab 2007a:
>> benchmark_index (4e6, 100)
time_slice1 = 3.573355
time_slice1s = 2.051805
time_slice1v = 6.820354
time_slice2c = 1.625231
time_slice2r = 5.991104
time_slice2cv = 1.493305
time_slice2rv = 6.671994
time_slicenc = 0.962447
time_slicend = 0.972687
time_slicens = 0.568007
time_slicen2 = 0.962911
time_spreadr = 4.748844
time_spreadc = 0.851502
FreeMat 4.0.1, fresh build (s LLVM) (doporučuju zajít po spuštění na oběd)
→ benchmark_index (4e6, 100)
time_slice1 = 47.162000
time_slice1s = 22.715000
time_slice1v = 43.019000
time_slice2c = 240.617000
time_slice2r = 242.140000
time_slice2cv = 243.359000
time_slice2rv = 242.150000
time_slicenc = 98.668000
time_slicend = 98.798000
time_slicens = 27.865000
time_slicen2 = 80.781000
time_spreadr = 241.160000
time_spreadc = 242.419000
zatímco Matlabu celý skript trvá 37 sekund (a to je tři roky stará verze), FreeMat se s ním moří více než půl hodiny. Pro srovnání, zde je Octave 3.3.51+:
octave:1> benchmark_index (4e6, 100)
time_slice1 = 0.000502
time_slice1s = 1.084566
time_slice1v = 1.972065
time_slice2c = 0.000671
time_slice2r = 1.630831
time_slice2cv = 1.505355
time_slice2rv = 1.723218
time_slicenc = 0.000915
time_slicend = 0.541328
time_slicens = 0.498534
time_slicen2 = 0.783243
time_spreadr = 1.350102
time_spreadc = 0.911790
to není tak úplně fér, protože 3.3.51+ není stable release a tahle binárka je navíc sestavená s celkem agresivním -O3 -march=native. 3.2.4 s výchozím nastavením je v některých bodech znatelně horší:
octave:1> benchmark_index (4e6, 100)
time_slice1 = 0.000623
time_slice1s = 1.093462
time_slice1v = 4.181895
time_slice2c = 0.000865
time_slice2r = 1.708514
time_slice2cv = 1.629910
time_slice2rv = 1.732078
time_slicenc = 0.001144
time_slicend = 0.569461
time_slicens = 0.494025
time_slicen2 = 1.137449
time_spreadr = 1.358040
time_spreadc = 1.359391
Je paradoxní, že ačkoliv FreeMat podporuje JIT kompilaci (jako Matlab) a Octave nikoliv, snad na všech reálných i pokusných skriptech mi FreeMat chodí pomaleji, někdy dost výrazně. Z toho je vidět že i z pouhého interpretru se dá vytřískat celkem dost, pokud se v něm programuje stylem lepení vestavěných funkcí a ty jsou silně optimalizované. Kdyby bylo možné oba projekty (octave a FreeMat) spojit a z každého si vzít to lepší, výsledek by zřejmě byl skvělý.
V každém případě, existují:
1. lži
2. velké lži
3. benchmarky
Samozřejmě záleží na situaci. V mých konkrétních problémech se vždy ukázal Matlab jako výrazně rychlejší. Je to možná dáno typem řešených problémů – u mě to byly poměrně jednoduché výpočty bez složitých datových struktur, které se opakovaly v mnohonásobných smyčkách a při nichž se generovala náhodná čísla. Stejný program ve FreeMatu byl vždy cca 10× pomalejší.
Na druhou stranu misím říct, že jsem u Matlabu zaznamenal obrovské zrychlení mezi verzemi 2006 a 2007.
Nechci dělat tady Matlabu reklamu, ale situaci, kdy některá operace trvá v Matlabu déle než ve Freematu považuji za málo pravděpodobnou.
P.S: Aby nedošlo k mýlce – FreeMat považuji za skvělý nástroj pro domácí kutění a poloprofesionální práci. Na skutečný profi segment však nemá.
No, já s vámi v zásadě souhlasím, výše uvedený benchmark ukazuje, že FreeMat je mnohem pomalejší i s dost základními operacemi. Na druhou stranu, na ml Octave se občas objevují lidé stěžující si, že jim skript v Octave jede velmi pomalu (a v Matlabu mnohem rychleji), a po nakouknutí v tom najdete věci jako (reálný příklad):
nans = [];
for i=1:length(fx), if ~isfinite(fx(i)), nans = [ i , nans ]; fx(i) = 0.0; end; end;
Přesněji by to bylo (ve smyčce se indexy přidávají dopředu, takže budou sestupně)
nans = fliplr(find(~isfinite(fx)));
fx(nans) = 0;
ale je dost možné, že v tom skriptu na pořadí nans nezáleželo. V každém případě tohle je jak efektivnější (v Octave určitě, dost možná i v Matlabu), tak čitelnější. Pokud někomu připadá čitelnější ta smyčka, možná by měl zvážit programování v něčem jiném.
Freemat mne, abych rekl pravdu, nezajima, ale srovnani Matlab vers. Octave je pro mne velkym prekvapenim. Naposledy jsem Octave pouzival pred cca 5 lety a tehdy byla jeho rychlost s porovnani s Matlabem ve vetsine skriptu ktere jsem testoval nizsi (typicky o cca 30–50%). Matlab pouzivam uz vice jak 10 let a troufnu si tvrdit, ze uz umim vyzdimat z tohoto systemu vetsinou maximum , ktere je schopen poskytnout.
Nedalo mi to a Octave 3.2.3 jsem si nainstaloval (Ubuntu 10.04 64bit). A zazil jsem opakovane prekvapeni, protoze jsem vase vysledky potvrdil.
To co tady uvadite, neni rozdil v rychlosti 30–50%, ale vyrazny radovy rozdil, ktery jasne signalizuje, ze v Matlabu se deje neco dost spatneho.
Mate tuseni v cem by mohl byt zakopany pes?
No, mluvíte-li o řádových rozdílech, zřejmě máte na mysli časy
time_slice1, time_slice2c a time_slicenc. „c“ zde znamená „contiguous“, a v tom je zakopaný pes.
Octave se totiž pokusí detekovat, zda je výsledkem indexového výrazu souvislý rozsah prvků (např. a(:,:,1), b(:,3:7)) a pokud ano, použije sdílenou kopii, tj. jen upraví ukazatel a deskriptor pole, ale data fyzicky nekopíruje, dokud se do nich nepokusíte zapisovat. Jde o stejný mechanismus, který používá i Matlab při kopírování celých proměnných:
a = rand (1000);
b = a; % tady se data fyzicky nekopírují, b a a ukazují na stejné pole
b(1) = 2; % teprve tady se vynutí kopie
Rozdíl je tedy v tom, že Octave od v. 3.2 tohle umí použít i na souvislé indexové výrazy. Jedno z mých vlastních vylepšení :)
Srovnání tedy není zcela fér, protože samozřejmě pokud kopii následně vynutíte, kopírování souvislého bloku paměti bude asi stejně rychlé v obou systémech (použije se memcpy).
Matlab na tom není o tolik hůř, protože JIT překladač umí souvislé indexy vyoptimalizovat. Pokud tedy v Matlabu napíšete
b = a(:,1) + 1;
a(:,1) se nebude kopírovat do samostatného pole. Naproti tomu, pokud uděláte
b = moje_funkce (a(:,1));
kopírovat se bude. V Octave se nebude kopírovat ani v druhém případě, pokud se nepokusíte ve funkci moje_funkce vstupní argument modifikovat.
Jak říkám, pozor na benchmarky, jsou zrádné. Je třeba rozumět tomu, co se děje, abychom vyvodili správné závěry.
ano … mat pravdu, jde o souvisle indexove vyrazy, ktere Matlab kopiruje na rozdil od Octave. Ted si uvedomuji, ze jsem na tenhle problem narazil v minulosti uz nekolikrat a resil jsem to specializovanym, jednoucelovym MEX filem psanym ve fortranu, abych akceleroval vypocet napr. c(i,j,n)= a(i:j).*a(i+n:j+n).
Smutne je, ze s tim MathWorks zatim nic nedela, ani verze Matlab 2010a na tom neni lepe. Netusim, zda pro ignorovani teto veci ma Matlab nejake hlubsi vnitrni duvody, ale je to zasadni nedostatek Matlabu, ktery nelze nijak elegentne za pomoci standardnich nastroju, kterymi Matlab disponuje vyresit.
Presto diky za vysvetleni …
No, možná by to nebylo nic jednoduchého. V Octave to nebyl zas takový problém, ale je možné, že ve vnitřnostech Matlabu je problém daleko komplexnější. Každopádně, MathWorks celkem pochopitelně respektuje přání zákazníků zejména podle toho, kolik má z nich peněz, takže je možné, že o to prostě není ze strany velkých zákazníků zájem. Na nějakých fórech jsem dotaz na tuhle věc párkrát viděl a odpověď byla myslím vždy taková, že to není v budoucnu vyloučeno, ale zatím to není v plánu. Výpočetní „jádra“ je stejně nejlepší psát ve Fortranu/C++, takže když to umíte, nemusí vás to tak moc pálit.