Zkušenosti s jazykem D

Sten

Re:Zkušenosti s jazykem D
« Odpověď #90 kdy: 26. 02. 2014, 21:04:42 »
Nahradil jsem všechny fory, ne jen jeden. Na mém počítači se tím srazil čas ze 12 sekund na 2,5.
Nepoužil jsi náhodou icc? Ten mi jednou podobný kód zoptimalizoval tak, až mi ho vyoptimalizoval úplně pryč.

Nn, g++ --std=c++11 -O3 -o test test.cc. Nejspíš to provede částečný unroll (při neustálém ptaní se na size to nejde udělat, protože se mezitím může změnit), takže se tam přes superskalární frontu bude počítat několik hodnot najednou.


RAII

Re:Zkušenosti s jazykem D
« Odpověď #91 kdy: 26. 02. 2014, 21:14:38 »
Nechci do toho kecat, ale ta blbá funkce size tam byla zbytečně volaná zhruba 2200. Tobě se to zrychlilo o 10s. Takže by jedno volání funkce size sežralo 22ms. A TO JE blbnost. Laskavě se koukni na to, co funkce size() dělá. Nevolá žádnou další funkci a její tělo tvoří jediný return jež dojde k vrácené hodnotě přímo. Tam opravdu 22ms nanejdeš. PS. to s tou superskalární frontou ... napiš jakej máš processor...

Sten

Re:Zkušenosti s jazykem D
« Odpověď #92 kdy: 26. 02. 2014, 21:18:57 »
No, tak sem to pěkně zoptimalizoval no ... na 700 ms takže 0,7s xDDD BTW mám 2 core pentium 3 GHZ (jo jasně někdo to bude mít i v C++ za pár milisekund když použije ňáký monstrum).  BTW, ten source code tady nedávám jen tak pro srandu, zkuste si zkompilovat i ten kód Dčka. Jasně máš to za 2,5 sekundy, ale jakej máš stroj? Skus tam zkompilovat i D a uvidíš že bude zase rychlejší!

Kód: [Vybrat]
module zkouskarychlosti;

import std.stdio;
import std.random;
import std.datetime;
import std.c.stdlib;

pure void mAdd(T)(T * matA, const T * matB, in long sm)
{
matA[0..sm] += matB[0..sm];
}

void mWrite(T)(const T * mat,in long width, in long heigth)
{
long totalS = width * heigth;
foreach (long i;0..totalS)
{
if (i == width)
writeln(" ");
write(mat[i]);
write("  ");
}
writeln(" ");
}

void main()
{
StopWatch sw;
sw.start();
int * v0 = cast(int*)malloc(1000*int.sizeof);
int * v1 = cast(int*)malloc(1000*int.sizeof);
foreach (int i;0..1000)
{
v0[i] = v1[i] = uniform(0,9);
}
foreach (int i;0..1000000)
{
mAdd(v0,v1,1000);
}
writeln(sw.peek().msecs());
sw.stop();
free(v0);
free(v1);
}

Mám trochu výkonnější procesor (Intel Core i7 2 GHz) ale tohle proběhne za 5 ms (ano, pět) měřeno přes time, samotný výpočet je za méně než 1 ms (pod hranicí měřitelnosti):
Kód: [Vybrat]
#include <iostream>
#include <random>

template <typename T,
          unsigned size>
void mAdd(T (&matA)[size],
          const T (&matB)[size])
{
        for (long i = 0; i < size; ++i)
                matA[i] += matB[i];
}

int main()
{
        std::random_device rnd;
        int v0[1000];
        int v1[1000];
        for (int i = 0; i < 1000; ++i)
                v0[i] = v1[i] = rnd() % 10;
        for (int i = 0; i < 1000000; ++i)
                mAdd(v0,v1);
        return 0;
}

Sten

Re:Zkušenosti s jazykem D
« Odpověď #93 kdy: 26. 02. 2014, 21:20:48 »
Nechci do toho kecat, ale ta blbá funkce size tam byla zbytečně volaná zhruba 2200. Tobě se to zrychlilo o 10s. Takže by jedno volání funkce size sežralo 22ms. A TO JE blbnost. Laskavě se koukni na to, co funkce size() dělá. Nevolá žádnou další funkci a její tělo tvoří jediný return jež dojde k vrácené hodnotě přímo. Tam opravdu 22ms nanejdeš. PS. to s tou superskalární frontou ... napiš jakej máš processor...

Superskalární frontu má každý procesor od Pentia Pro ;)

Sten

Re:Zkušenosti s jazykem D
« Odpověď #94 kdy: 26. 02. 2014, 21:26:14 »
Nechci do toho kecat, ale ta blbá funkce size tam byla zbytečně volaná zhruba 2200. Tobě se to zrychlilo o 10s. Takže by jedno volání funkce size sežralo 22ms. A TO JE blbnost. Laskavě se koukni na to, co funkce size() dělá. Nevolá žádnou další funkci a její tělo tvoří jediný return jež dojde k vrácené hodnotě přímo. Tam opravdu 22ms nanejdeš. PS. to s tou superskalární frontou ... napiš jakej máš processor...

Ne, volá se tam zbytečně asi tak 1 000 000× (ty iterace jsou kvadratické, nesčítají se, ale násobí). Ta funkce se samozřejmě inlineuje, ale neustálé čtení paměti a porovnávání kromě spousty zbytečných tiků taky dost rozbíjí branch predictions a klidně to může mít takovýhle brutální zpomalení.


RAII

Re:Zkušenosti s jazykem D
« Odpověď #95 kdy: 26. 02. 2014, 21:34:15 »
To víme taky ... mě jen zajímalo kolik pipeline má tvoje jedno jádro ... a ano. U mě to trvá taky jen kolem 2ms (to ukazuje vždy ať je v programu cokoli -> chyba měření). Na první pohled si mne tvrdě rozdrtil ale ... ty máš v tý funkci tvrdě přes šablony zadrátovaný počet prvků, jako argument můžeš dát pouze staticky alokované pole (v době kompilace). A to je právě kámen úrazu. Můj kód není závislí na ničem takovém. Vše je pružné, nic není nutno znát v době kompilace. Takže opět, nemůžu uznat porážku neb tvůj program nezvládne to co můj. P.S. Nezdá se mi to tvoje zrychlení o 10s jen díky odstranění tý funkce size, i přesto že máš i7, je to nesmysl (já mám Pentium za tisícovku).

RAII

Re:Zkušenosti s jazykem D
« Odpověď #96 kdy: 26. 02. 2014, 21:41:46 »
Dostals mě, funkce size se tam volá 20200. To dává zhruba 0,5 ms za sekundu. Ve funkci size() je 13 instrukcí. Najdi si jaký IPS má tvůj procesor. Ale ve zkratce: 0,5ms na 13 instrukcí je hezká pohádka. Přístup do cache je zhruba 8 ns a jedna instrukce je 1ns. Přístup do registru zhruba 2ns. Zpočítej si to a uvidíš ten extrém xD (ty hodnoty sem někde vyděl na stránkách, netušim jak starý sou, dneska může být všechno rychlejší + i7...)

RAII

Re:Zkušenosti s jazykem D
« Odpověď #97 kdy: 26. 02. 2014, 21:42:54 »
Hovno " To dává zhruba 0,5 ms za sekundu." -> má být To dává 0.5ms na jedno volání funkce size

Sten

Re:Zkušenosti s jazykem D
« Odpověď #98 kdy: 26. 02. 2014, 21:44:42 »
To víme taky ... mě jen zajímalo kolik pipeline má tvoje jedno jádro ... a ano. U mě to trvá taky jen kolem 2ms (to ukazuje vždy ať je v programu cokoli -> chyba měření). Na první pohled si mne tvrdě rozdrtil ale ... ty máš v tý funkci tvrdě přes šablony zadrátovaný počet prvků, jako argument můžeš dát pouze staticky alokované pole (v době kompilace). A to je právě kámen úrazu. Můj kód není závislí na ničem takovém. Vše je pružné, nic není nutno znát v době kompilace. Takže opět, nemůžu uznat porážku neb tvůj program nezvládne to co můj. P.S. Nezdá se mi to tvoje zrychlení o 10s jen díky odstranění tý funkce size, i přesto že máš i7, je to nesmysl (já mám Pentium za tisícovku).

Vytáhl jsem to nejlepší, co dokáže C++, tak zněla pravidla ;)

Pokud tam dám dynamické velikosti, zpomalí se to na 210 až 230 ms. To Déčko zkompilované přes gdc -O3 to udělá za 770 až 800 ms.

Dostals mě, funkce size se tam volá 20200. To dává zhruba 0,5 ms za sekundu. Ve funkci size() je 13 instrukcí. Najdi si jaký IPS má tvůj procesor. Ale ve zkratce: 0,5ms na 13 instrukcí je hezká pohádka. Přístup do cache je zhruba 8 ns a jedna instrukce je 1ns. Přístup do registru zhruba 2ns. Zpočítej si to a uvidíš ten extrém xD (ty hodnoty sem někde vyděl na stránkách, netušim jak starý sou, dneska může být všechno rychlejší + i7...)

Ne, volá se to víc než milionkrát. Jen v:
Kód: [Vybrat]
for (int i=0; i<first.size(); ++i)
        {
            for (int y=0; y<first[i].size(); ++y)
            {
se volá 1 001 000 × (1 000 × ve vnějším foru a 1 000 × ve vnitřním foru pro každou iteraci vnějšího foru).

RAII

Re:Zkušenosti s jazykem D
« Odpověď #99 kdy: 26. 02. 2014, 22:00:37 »
juj, chybka, Zapoměl sem započítat ještě cykli v sčítací funkce takže je to 30200 volání (jakej milion?? 100*100=10000*3=30000). Takže místo 0,5 ms to je  0,33 ms což je 330 ms -> 330 000 mikros -> 330 000 000 ns. Nahoře sem psal 13 instrukcí a kolik zhruba zaberou času. Takže furt máš co vysvětlovat. Jo jasně, nedohodli sme jasná pravidla...vyhrál si. ALE, stejnou schopnost má i D (staticky alokovaná pole + hodnotové parametry šablon). takže to můžu na 2ms dát jak ty.

RAII

Re:Zkušenosti s jazykem D
« Odpověď #100 kdy: 26. 02. 2014, 22:01:44 »
jo...zase chyba. Bude to ten 1000 000...

JSH

Re:Zkušenosti s jazykem D
« Odpověď #101 kdy: 26. 02. 2014, 22:03:17 »
On je v tom originálním kódu ještě jeden brutální zádrhel a to
Kód: [Vybrat]
a[i][j] += b[i][j]
Při každém indexování prvku to leze nejdřív do vnějšího vektoru aby z něj vytáhlo znova a znova odkaz na stejný řádek. Proč to překladač nedokáže zoptimalizovat nevím, možná kvůli potenciálnímu aliasu. Hlavně to nejspíš nikdo neřeší, protože tenhle typ kódu se v kritických částech nevyskytuje a pokud ho někdo použije, dobře mu tak.

Dčkový přístup odpovídá tomu, kdyby se v C++ použila místo vnitřního vectoru valarray. Ta se ovšem takřka nepoužívá, protože tam kam se hodí valarray se obvykle hodí i daleko mocnější expression templates.

RAII

Re:Zkušenosti s jazykem D
« Odpověď #102 kdy: 26. 02. 2014, 22:03:29 »
Takže 0,01 ms. to je 10 ms -> 10 000 000 ns. Furt mi to na těch 13 instrukcí nesedí xDD ale máš pravdu, to s tím počítáním funkcí sem posral totálně

Sten

Re:Zkušenosti s jazykem D
« Odpověď #103 kdy: 26. 02. 2014, 22:11:04 »
Takže 0,01 ms. to je 10 ms -> 10 000 000 ns. Furt mi to na těch 13 instrukcí nesedí xDD ale máš pravdu, to s tím počítáním funkcí sem posral totálně

0,01 ms je 10 000 ns ;)

RAII

Re:Zkušenosti s jazykem D
« Odpověď #104 kdy: 26. 02. 2014, 22:12:15 »
No tak nic no :( zkusil sem to zoptimalizovat šablonama a dalo to 880 ms (!VÍC!). V tomto má GDC mezeru, není to ale chyba jazyka ...