Zobrazit předchozí téma :: Zobrazit následující téma |
Autor |
Zpráva |
frca
Založen: 28. 07. 2007 Příspěvky: 1561
|
Zaslal: 10. leden 2022, 17:41:46 Předmět: Celočíselná interpolace |
|
|
Zdravím,
přemýšlím, jak urychlit interpolaci, aby se v každém kroku nepoužívalo násobení a dělení. Prostě nějak rozdistribuovat ten zbytek... Netušíte? Díky.
kód: |
#include <iostream>
void naiveLerp(int len, int value)
{
for (int i = 0; i <= len; ++i)
{
std::cout << value * i / len << " "; // expensive
}
std::cout << std::endl;
}
// FIXME
void fastLerp(int len, int value)
{
int q = value / len; // podíl (quotient)
int m = value % len; // dá se nějak využít modulo?
int sum = 0;
for (int i = 0; i <= len; ++i)
{
std::cout << sum << " ";
sum += q;
// ?
}
std::cout << std::endl;
}
int main()
{
naiveLerp(17, -27);
fastLerp(17, -27);
return 0;
}
|
_________________ www.FRANTICWARE.com |
|
Návrat nahoru |
|
|
Ladis
Založen: 18. 09. 2007 Příspěvky: 1537 Bydliště: u Prahy
|
Zaslal: 10. leden 2022, 20:34:36 Předmět: |
|
|
Můžeš optimalizovat výpočet nad tímto. Např. ve 3D se dá interpolace nahradit obyčejnými additions (víš odkud kam jdeš, tak si spočítáš jen přírůstky - samozřejmě s nějakými bity navíc pro přesnost). _________________ Award-winning game developer |
|
Návrat nahoru |
|
|
frca
Založen: 28. 07. 2007 Příspěvky: 1561
|
Zaslal: 10. leden 2022, 20:57:32 Předmět: |
|
|
Jasně, víc bitů, to mě napadlo. Ale já doufám v nějaký způsob, jak dotlačit fastLerp, aby měl identický výsledek jako naiveLerp. _________________ www.FRANTICWARE.com |
|
Návrat nahoru |
|
|
mar
Založen: 16. 06. 2012 Příspěvky: 610
|
Zaslal: 11. leden 2022, 08:00:04 Předmět: Re: Celočíselná interpolace |
|
|
záleží, jakých hodnot může value nabývat. s fixed pointem bys to měl sčítání plus shift
pokud bys šel do assembly, dalo by se udělat něco víc fancy, kdysi se používal takový trik, že ten fixed point byl uložený naopak, tzn.
fractional part byla uložená ve vyšších bitech, pak by ti stačilo třeba toto
kód: |
add eax, ebx
adc eax, 0
|
tzn. pomocí carry vyteče fract part, kterou v dalším kroku přičteš s celočíselné
a v ax bys pak měl celočíselnou část, řekněme fp16:16
|fract_part 16 bits|int_part 16 bits|
a pokud by se ti povedlo uvnitř smyčky zachovat carry flag, tak ho stačí na začátku smyčky vymazat a pak se to smrskne ja jednu instrukci
samozřejmě zajímavější je tento způsob o to víc, když interpoluješ dvě hodnoty, třeba uv pro texturování, se zachováním carry flagu:
|v_frac|u_int|
|u_frac|v_int|
kód: |
adc eax, ecx
adc ebx, edx
|
cool, ne?
EDIT: samozřejmě toto ale předpokládá, že ti celočíselná část nevyteče do fractional takže s těmi negativními hodnotami by to bylo trochu tricky... i když pokud by počet pixelů byl relativně malý, tak ta chyba by asi mohla být přijatelná |
|
Návrat nahoru |
|
|
frca
Založen: 28. 07. 2007 Příspěvky: 1561
|
Zaslal: 11. leden 2022, 08:54:03 Předmět: |
|
|
Hodně zajímavé, díky
S tím UV jsem to ale asi nepochopil... _________________ www.FRANTICWARE.com |
|
Návrat nahoru |
|
|
mar
Založen: 16. 06. 2012 Příspěvky: 610
|
Zaslal: 11. leden 2022, 09:21:56 Předmět: |
|
|
no něco takového třeba:
kód: |
...init...
mov edx, [texture_ptr]
// clear carry
and edx,edx
loop_start:
mov dl, al
mov dh, bl
adc eax, ebp
// texture fetch
mov dl, [edx]
adc ebx, esi
// buffer store
mov [edi], dl
inc edi
dec ecx
jnz loop_start
|
a samozřejmě toto je naivní smyčka, která by se dala rozrolovat/přeskládat/zjednodušit apod.
tady se předpokládá textura 256x256, pointer zarovnaný na 64kb
prostě to rozeskládání je důležité, aby přetékal u_frac to u_int a opačně, jak jsem psal
navíc můžeš v tomto konkrétním případě klidně FP8:24 pro lepší přesnost
EDIT: těch registrů je fakt málo pokud bys během toho zakázal přerušení, dal by se využít i esp třeba jako čítač a uvolnilo by to ecx na něco zajímavého třeba jako na temp akumulátor a v rozrolované smyče by pak uložení mohlo být třeba mov [edi+nn], cx, za předpokladu, že jedeš horizontálně, možností je spousta prostě
ještě jedna drobnost: add ničí carry, ale pak tu je lea, kterou se dá fejkovat třeba add reg,4 => lea reg, [reg+4] apod. |
|
Návrat nahoru |
|
|
OndraSej
Založen: 28. 07. 2007 Příspěvky: 767 Bydliště: Brandýs nad Labem
|
|
Návrat nahoru |
|
|
|