Problém s výkonem - procházení bitmapy – C / C++ – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

Problém s výkonem - procházení bitmapy – C / C++ – Fórum – Programujte.comProblém s výkonem - procházení bitmapy – C / C++ – Fórum – Programujte.com

 

Toto vlákno bylo označeno za vyřešené — příspěvek s řešením.
oxidián0
Grafoman
19. 2. 2015   #1
-
0
-

Mám tři knihovny na načítání obrázků. Funkce libjpeg začíná takto:

bool read_jpg_file(pJPEG_DATA data)
{
    data->row_bytes_len = data->d_info.output_width * (data->d_info.output_components);
    data->pRowsArray = (data->d_info.mem->alloc_sarray)
                ((j_common_ptr) &data->d_info, JPOOL_IMAGE, data->row_bytes_len, 1);

    size_t counter=0;
    data->image_buffer =
    (unsigned char*) malloc( data->channels * data->width * data->height );

    while (data->d_info.output_scanline < data->d_info.output_height)
     {
     (void) jpeg_read_scanlines(&data->d_info, data->pRowsArray, 1);


     for( a=0; a<data->row_bytes_len ; a+=c)
        {

Něco podobného je i u lipng, tak že zdroj se načítá po řádcích. Funkce výše alokuje paměť pro celý obraz rgb a pak ho procházím a provádím rgb2hsv. Celé to zabere jen zlomek vteřiny. To samé u png, i když tam je smyčka která prochází dvourozměrým polem.  Tedy existuje pole pointerů, která odkazuje na jednotlivé řádky a to se pak prochází

for (y=0; y<data->height; y++)
    {
    for (x=0; x<data->row_bytes_len; x=x+c)
        {
        if( !data->row_pointers[y][x+1] ) {
            // set all values to V
            data->row_pointers[y][x]=data->row_pointers[y][x+2];
            data->row_pointers[y][x+1]=data->row_pointers[y][x+2];
            continue;
        }

        H=(float) data->row_pointers[y][x];
        S=(float) data->row_pointers[y][x+1];
        V=(float) data->row_pointers[y][x+2];
...


Opět kód zabere jen malou chvilku, i když záleží to na typu obrazu.

Mluvím o rgb obrazu o rozměrech 4096x4096 px.

No a nyní mám knihovnu, která pracuje s bmp a ta načte vše do jednoho bufferu a trvá to 10s což je extrémně dlouhá doba. Tak se chci zeptat jestli nevíte proč, co bych mohl udělat aby se to časově přiblížilo k těm dvouma nahoře. Načtení bitmapy proběhne bleskově, ale ten proces zpracování trvá hodně dlouho. Chyba v kódu konverze by určitě být neměla. Kód začíná...

void bmp_rgb2hsv(BMPFILE * bmpfile)
{
    float R, G, B, H, S, V,min, max, delta, rev_delta;
    H=S=V=0;
    uint32_t c = bmpfile->channels;
    uint32_t a;
    for (a=0; a < bmpfile->dib.raster_size; a+=c)
       {
       R=(float) bmpfile->buffer[a];
       G=(float) bmpfile->buffer[a+1];
       B=(float) bmpfile->buffer[a+2];
...

 ... jen jedna smyčka, která se navyšuje o 3 v každém cyklu. Vstupní hodnoty jsou samozřejmě správné

Nahlásit jako SPAM
IP: 78.45.199.–
Satik0
Stálý člen
19. 2. 2015   #2
-
0
-

#1 oxidián
Je ten bmpfile->buffer jen obyčejné pole (pointer)? Není za tím třeba skrytá ještě nějaká logika?

A co ten zbytek funkce?

Nahlásit jako SPAM
IP: 86.49.188.–
oxidián0
Grafoman
19. 2. 2015   #3
-
0
-

buffer je

unsigned char * buffer;

a žádná logika tam není. Jen se do toho načte ten obraz bmp, to je vše. Zbytek funkce provádí to co se provádí při HSV konverzi. Končí to takto:

bmpfile->buffer[a]=(uint32_t)(H*0.002777*255 + 0.5);
bmpfile->buffer[a+1]=(uint32_t)(S*255 + 0.5);
bmpfile->buffer[a+2]=V;


Jen dodám, že typ int jsem nahradil za uint32_t to je jediná změna, kterou jsem udělal v kódu. Jeden kluk má podobný problém s bitmapama a tvrdí že se mu taky bmpéčka zpracováváají děsně pomalu a ještě pomaleji než mě, ale o programování v C toho ví podstatně víc než já a jeho kód jsem neviděl.

Nahlásit jako SPAM
IP: 78.45.199.–
Satik0
Stálý člen
19. 2. 2015   #4
-
0
-

Jsi si jistý, že je problém v tom zpracování kódu a ne načítání?

Pošli sem kdyžtak celý ten kód, tady jsem nic zpomalujícího neviděl.

Případně můžeš použít profiler, třeba http://www.codersnotes.com/sleepy - ten ti ukáže, kde program tráví nejvíc času.

Nahlásit jako SPAM
IP: 86.49.188.–
oxidián0
Grafoman
19. 2. 2015   #5
-
0
-

Tak celý program se mi na internet dávat nechce. Přeci jen jsem nad tím ztrávil dost času. Načítání je provedeno během zlomku vteřiny. Čas měřím až od chvíle kdy se chystám spustit konverzi. Naměřený čas pak hned za konverzí vytisknu.

Teď jsem začal zakomentovávat jednotlivé části kódu a toto zabere dvě vteřiny:

delta = max - min;
rev_delta = 1 / delta; // trvá 2 s

max a min jsou minimální a maximální hodnota ze tří čísel RGB. Zbytek všeho ostatního trvá 0.2s, ktomě spodní části konverze, kterou jsem zakomentoval.

Není mi však jasné proč v png_rgb2hsv to problém nedělá

poznámka:

To s tím sice nesouvisí ale napadlo mě, že bych mohl udělat pole s možnými výsledky rev_delta a ten výsledek si najít před tím než spustím cyklus.1 / (max-min) bude mít maximálně cca 128*253 řešení (32385).

Nahlásit jako SPAM
IP: 78.45.199.–
Satik0
Stálý člen
19. 2. 2015   #6
-
0
-

Bez kódu se radí težce :)

Ještě můžeš zkusit všechny ty výpočty předělat na celá čísla, to by mělo hodně pomoci.

Nahlásit jako SPAM
IP: 86.49.188.–
oxidián0
Grafoman
19. 2. 2015   #7
-
0
-

Jo a bylo by to hodně nepřesné. Sice nevím s jak velkou přesností musím počítat - bohužel - ale k nečemu tam ten float asi je ...rev_delta slouží k výpočtu odstínu.

Jenže proč předělávat algoritmus, když na png a jpg to jede?

Teď jsem zjistil že v kodu je mala chybka:

rev_delta = 1 / delta;

místo

rev_delta = 1.0 / delta;

takže jsem často dostával špatné výsledky (0 místo desetinné číslo).

Nahlásit jako SPAM
IP: 78.45.199.–
peter
~ Anonymní uživatel
4014 příspěvků
19. 2. 2015   #8
-
0
-

(H*0.002777*255 + 0.5);
1.0 / delta

Pokud delas operace s mnoha cisly opakovane, tak tohle je vec presne na pikacu. Kdyz treba v php delam nejake transformace se souborem, tak si vyrobim pole s vysledky operaci.

Treba
$arr = array(); for ($i=0;$i<256;++$i) {$arr[chr($i)] = $i;}
$out = array(); for ($i=0;$i<$delka_souboru;++$i) {$out = $arr[ $input[$i] ];} // je to rychlejsi nez prime ord()
//$out = array(); for ($i=0;$i<$delka_souboru;++$i) {$out = ord( $input[$i] );}

Takze, jestli pracujes s bitmapou a znas predem vysledky nekterych operaci, treba prave transformace pres barevny model s H, tak je lepsi si to vypocitat predem do pole a pouzit vysledek z pole.

Nahlásit jako SPAM
IP: 2001:718:2601:1f7:c151:34...–
peter
~ Anonymní uživatel
4014 příspěvků
19. 2. 2015   #9
-
0
-

ups, samozrejme tam melo byt misto $out =
$out[] = nebo
$out[$i] =

Nahlásit jako SPAM
IP: 2001:718:2601:1f7:c151:34...–
Satik0
Stálý člen
19. 2. 2015   #10
-
0
-

#7 oxidián
I kdyby jsi mel pouzit 64bitova cela cisla (coz ale potreba nejspis nebude a budou stacit 32bitova), tak to bude rychlejsi nez desetinna cisla.

float preci taky umi ulozit jen 32bitu informaci. A predpokladam, ze ve tvych vypoctech je celkem omezeny rozsah, jakeho ta cisla mohou nabyvat.

Nahlásit jako SPAM
IP: 86.49.188.–
oxidián0
Grafoman
19. 2. 2015   #11
-
0
-

Peter: Jenže PHP a C nemůžeš srovnávat. PHP nemá předem nadefinované všechny typy tak jak v C a program v C si předkompiluješ. V PHP jsem taky dělal tyhle věci a jely mi rychleji než tady to v C, ale to byl malý obrázek o rozměrech třeba 100x100 ted tam mám 4096x4096 a jak říkám záhada je hlavně to že v libpng a jpeglib s tímhle není problém.

Ohledně ne/přesnosti s celými čísly. Ted jak na to koukám tak ta delta resp. rev. delta se týká odstínů, ale odstíny mají maximální hodnotu 360, kdežto pixely 255, takže když to pak zase budu ukládat do rgb obrazu s 8 bity na kanál, tak to se vlastně stejně ztratí. Nicméně je tam i násobení, takže pokud mám např. 2+(B-R)*rev_delta tak výjde např 2+100*rev_delta takže se desetinná čárka posune o dvě místa. Takže tři místa tam nejspíš roli hrát budou.

Zkouším tuto funkci

Zkusil jsem vytvořit funkci na předběžný výpočet:

Mám dvě pole:

float ** MinMaxRevDelta; // MinMaxRevDelta_createArray(float ** MinMaxRevDelta, float ** SatDeltaDivMax)

float ** SatDeltaDivMax; // MinMaxRevDelta_createArray

MinMaxRevDelta_createArray(float ** f1, float ** f2){
    unsigned char a,b;
    uint32_t c; c=0;

    f1 = malloc((sizeof (float)) * 254 );
    f2 = malloc((sizeof (float)) * 254 );
    for (a=1; a<255; a++) // a = max
    {
    f1[a] = malloc((sizeof (float)) * a );
    f2[a] = malloc((sizeof (float)) * a );
    for (b=0; b<0+a; b++) // b = min
        {
        f1[a][b]=1.0/(a-b); // delta: max / min
        f2[a][b]=(a-b)/a; // Saturation: delta / max
        // printf("min:%d, max:%d\n",b,a);
        c++;
        }
    }
    // printf("c:%d",c);
}

Volám z main():

MinMaxRevDelta_createArray(MinMaxRevDelta, SatDeltaDivMax);

nebo takto?

MinMaxRevDelta_createArray(&MinMaxRevDelta, &SatDeltaDivMax);


a potřebuji zpřístupnit ty pole které jsou uvnitř funkce nastaveny, ale nedaří se. Jak opravit?

Nahlásit jako SPAM
IP: 78.45.199.–
KIIV
~ Moderátor
+43
God of flame
19. 2. 2015   #12
-
0
-

zase mas o jednu uroven min :)

(float *** f1, *** f2)

volat s  &neco1, &neco2  kde tyhle jsou typu   float ** neco1, ** neco2;

a tak dale

Nahlásit jako SPAM
IP: 62.168.56.–
Program vždy dělá to co naprogramujete, ne to co chcete...
oxidián0
Grafoman
19. 2. 2015   #13
-
0
-

už to jede

MinMaxRevDelta_createArray(float *** f1, float *** f2){
    unsigned char a,b;
    uint32_t c; c=0;

    *f1 = malloc((sizeof (float)) * 254 );
    *f2 = malloc((sizeof (float)) * 254 );
    for (a=1; a<255; a++) // a = max
    {
    (*f1)[a] = malloc((sizeof (float)) * a );
    (*f2)[a] = malloc((sizeof (float)) * a );
    for (b=0; b<0+a; b++) // b = min
        {
        (*f1)[a][b]=1.0/(a-b); // delta: max / min
        (*f2)[a][b]=(a-b)/a; // Saturation: delta / max
        // printf("min:%d, max:%d\n",b,a);
        c++;
        }
    }
    // printf("c:%d",c);
}

MinMaxRevDelta_createArray(&MinMaxRevDelta, &SatDeltaDivMax);

Nahlásit jako SPAM
IP: 78.45.199.–
oxidián0
Grafoman
19. 2. 2015   #14
-
0
-

Jak zapsat toto:

void bmp_rgb2hsv(BMPFILE * bmpfile, float *** f1, float *** f2){

S = (*f2)[max][min];

když to krachuje ale ve watch panel vidím že *(*f2)[2] je 0.5? Předpokládám že *(*f2)[2] odkazuje na (*f2)[2][0]

Nahlásit jako SPAM
IP: 78.45.199.–
KIIV
~ Moderátor
+43
God of flame
19. 2. 2015   #15
-
0
-

#14 oxidián
tady uz *** nepotrebujes, staci predat pomoci ** a bez ziskavani reference

Nahlásit jako SPAM
IP: 62.168.56.–
Program vždy dělá to co naprogramujete, ne to co chcete...
ondrej39+1
Věrný člen
19. 2. 2015   #16
-
0
-

#16 oxidián
Proč to stejně tvoříš přes trojnásobný pointer? Není lepší použít dvojnásobný, na deklaraci dynamického dvojnásobného pole bohatě stačí...

Např.

int** ary = new int*[sizeX];
for(int i = 0; i < sizeX; ++i)
    ary[i] = new int[sizeY];
Nahlásit jako SPAM
IP: 46.39.172.–
Inject all the dependencies!
oxidián0
Grafoman
19. 2. 2015   #17
-
0
-

Píšu to v C.

Proč nemohu zvášit maximum a na <256 ? Vždycky to trvá moc dlouho

MinMaxRevDelta_createArray(float *** f1, float *** f2){
    unsigned char a,b;
    uint32_t c; c=0;

    *f1 = malloc((sizeof (float)) * 255 );
    *f2 = malloc((sizeof (float)) * 254 );
    for (a=1; a<256; a++) // a = max
    {
    (*f1)[a] = malloc((sizeof (float)) * a );
    (*f2)[a] = malloc((sizeof (float)) * a );
    for (b=0; b<0+a-1; b++) // b = min
        {
        (*f1)[a][b]=1.0/(a-b); // delta: max / min
        (*f2)[a][b]=(a-b)/a; // Saturation: delta / max
        // printf("min:%d, max:%d\n",b,a);
        c++;
        }
    }
    // printf("c:%d",c);
}
Nahlásit jako SPAM
IP: 78.45.199.–
ondrej39+1
Věrný člen
19. 2. 2015   #18
-
0
-

#17 oxidián
To je celkem jedno, v čem to píšeš. Nahraď new za malloc a jsi na tom stejném.

Ty for cykly se mi stejně nezdají. Co prvek na indexu [0][neco]? Začínáš s a=1, na nulu kašleš? Proč raději for cyklus neukončíš dřív a ukousneš pole na konci, namísto abys na nultém indexu neměl nic?

Nahlásit jako SPAM
IP: 46.39.172.–
Inject all the dependencies!
oxidián0
Grafoman
19. 2. 2015   #19
-
0
-

Nula není třeba. Jsou to hodnoty min a max z rozsahu 0 až 255. První cyklus je max a max je vždy větší než min, proto začíná jedničkou. 255 mi tam nejde dát když dám 255<= tak to trvá moc dlouho nevím proč

Nahlásit jako SPAM
IP: 78.45.199.–
KIIV
~ Moderátor
+43
God of flame
19. 2. 2015   #20
-
+1
-
Zajímavé

hlavne unsigned char ma maximalni hodnotu 255.. jakakoliv hodnota mensi nez 256 by mela byt teoreticky spravna -> nekonecny cyklus :)

Nahlásit jako SPAM
IP: 62.168.56.–
Program vždy dělá to co naprogramujete, ne to co chcete...
ondrej39+1
Věrný člen
19. 2. 2015   #21
-
0
-

#19 oxidián
Upřímně, jak se zpracovávají obrázky netuším, nedělal jsem to, nicméně na základě dotazů, které tu většinou máš, si bohužel myslím, že sis ukousnul moc velké sousto, které neumíš spořádat.

Už jen samotná iterace for cyklu pomocí charu namísto integeru mě překvapila, to vidím poprvé v životě a v C++ jsem o cyklech projel asi tak 100 návodů. Pokud se nemýlím, kromě deklarace interátoru mimo podmínkovou závorku se ale for cykly v C chovají stejně jako v C++.

Nahlásit jako SPAM
IP: 46.39.172.–
Inject all the dependencies!
oxidián0
Grafoman
19. 2. 2015   #22
-
0
-

A já se zas divím tomu proč by cyklus neměl jít pomocí unsigned char, i když jsem tu narazil na limit. Schopnost zvládat obecnou logiku algoritmů nijak nesouvisí se schopností zvládat pointery.

Nahlásit jako SPAM
IP: 78.45.199.–
oxidián0
Grafoman
19. 2. 2015   #23
-
0
-

Tak jo, povedlo se mi to zkrátit na 0.38-0.4s ale když přidám tyto řádky:

bmpfile->buffer[a]=(uint32_t)(H*0.002777*255 + 0.5);
bmpfile->buffer[a+1]=(uint32_t)(S*255 + 0.5);
bmpfile->buffer[a+2]=V;

tak to skočí na 0.609s

První věc která mě napadá jestli je nutné to přetypování,

druhá, jestli nebude lepší použít dělení místo násobení.

Kdybych se dostal na čas 0.4 tak by to docela ušlo.

0.41s bez těch tří řádků. 0.54s když namísto výpočtů dosadím nějaké celé číslo.

Zkrácením čísla 0.002777 na 0.00277 dojde k nepřesnosti ve stupních odstínu o 0.4-0.5° ale na rychlost to nemá vliv takže se nevyplatí zkracovat.

Tak na tom už asi nic neušetřím.

Edit:

Teď jsem se díval na ty časy u png a tam jsem měl 0.63s ale nevím u jak velkého souboru to byl myslím png soubor 3288x2416 takže taky to nebylo maximum a byla to barevná fotografie, takže načítání u takové fotky může trvat déle a zápis pak 5.5s. Tak s tímhle chytrým algoritmem ušetřím furu času.

Nahlásit jako SPAM
IP: 78.45.199.–
BDS+3
Věrný člen
19. 2. 2015   #24
-
0
-

#22 oxidián
proč by cyklus neměl jít pomocí unsigned char

samozřejmě jde, ale v tomto případě for (unsigned char a=1; a<256; a++) jde o naprostý nesmysl, protože se ve skutečnosti a se nemůže nikdy rovnat 256. Dobré vývojové prostředí by ti zde mělo nahlásit varování, takže buďto používáš nějakou sračku, nebo to varování ignoruješ.

signed char 0xFF == -1

unsigned char 0xFF == 255 

když dám 255<= tak to trvá moc dlouho nevím proč

protože, v případě unsigned char je to opět nekonečný cyklus

Nahlásit jako SPAM
IP: 31.47.99.–
W11 :)
oxidián0
Grafoman
20. 2. 2015   #25
-
0
-

Píšeš to zbytečně psal to tu už KIIV a zas tak blbý nejsem abych nevěděl že unsigned char nejde do záporu. Psal jsem že to použít jde ale s omezením. Jaká omezení jsem asi tak myslel?

Nahlásit jako SPAM
IP: 78.45.199.–
Satik0
Stálý člen
20. 2. 2015   #26
-
0
-

Za všechny desetinný čísla dopiš f ("0.5" -> "0.5f"), možná to pár tisícin nebo setin taky zrychlí, takhle počítáš s doublem.

Jinak opravdu zrychlení by jsi měl po přepsání desetinných čísel na celá.

Nahlásit jako SPAM
IP: 77.87.240.–
peter
~ Anonymní uživatel
4014 příspěvků
20. 2. 2015   #27
-
0
-

for (a=1; a<256; a++)
for (a=0; a<256; ++a) // nekdo psal, ze je dobre pouzivat ++a misto (mozna v jinem forku) a++ a mimochodem, cisla jsou 0-255 ne 1-255 (viz ondrej390 #17, ale to jsi psal, ze tam nepotrebujes)

(*f1)[a] = malloc((sizeof (float)) * a );
(*f2)[a] = malloc((sizeof (float)) * a ); // proc 2x po sobe delas stejnou operaci? proc to nezkopirujes z te prvni?

A proc tam mas vsude tolik prevodu, kdyz treba nejsou potreba. Staci mozna na zacatku.
 

(*f1)[a][b]=1.0/(a-b); // delta: max / min
(*f2)[a][b]=(a-b)/a; // Saturation: delta / max // printf("min:%d, max:%d\n",b,a);
c++;

x = a-b; // mozna to bude rychlejsi takto
(*f1)[a][b] = 1.0/x;
(*f2)[a][b] = x/a;
++c;


for (b=0; b<0+a-1; b++) // b = min
Jo, tohoto se lidi dopousti uplne nejvic, protoze je to tak v chytrych knizkach. Ale casove je to brzda.
y = 0+a-1;
for (b=0; b<y; ++b)
b<0+a-1 - to je podminka, takze v kazdem cyklu se musi provest scitani, protoze "a" je promenna a muze se zmenit uvnitr toho cyklu. Nevim, jestli to ma c++ nejak podchycene a sleduje to pri kompilaci, ale myslim, ze ne.

Nahlásit jako SPAM
IP: 2001:718:2601:1f7:10d7:56...–
Ovrscout
~ Anonymní uživatel
113 příspěvků
20. 2. 2015   #28
-
0
-

hmm, bez celého kódu včetně výsledků měřen nad stejnými daty se těžce radí,nicméně:

Pro cyklus se většinou používá int i když by stačilo něco menšího,protože výpočty s ostatními typy bývají pomalejší (nebo stejně rychlé) a paměť se také většinou neušetří, protože taková proměnná cyklu by mněla být buď v registru(hlavně v release režimu, s optimalizací) a ten má stejnou velikost bez ohledu na to co v něm je (víceméně) a nebo je někde na stacku a to také nebývá problém.
Každopádně použití něčeho jiného než int/unsigned int mi přijde jako předčasná optimalizace pokud nemáš změřeno že to dává lepší výsledky. A nebo nemáš nějaký jiný důvod, např int je příliš malý nebo potřebuješ cyklovat nad floatem atd.

Když vidím  rev_delta = 1.0 / delta , tak by mne zajímalo, zda je nějak zajištěno že delta nebude nula.
To by pak mohlo dělat různé zajímavé věci, a mohlo by to mít i vliv na výkon.

JInak by stálo za to porovnat výkon těch algoritmů v release režimu se zapnutými optimalizacemi (-O2)
Nad stejným obrázkem(i když třeba u jpg se díky ztrátové kompresi se můžou data rasteru od ostatních lišit).
Ono se to v release režimu a s optimalizacemi může chovat dost jinak, a možná to ani nebude třeba dál řešit.

Nahlásit jako SPAM
IP: 193.165.79.–
peter
~ Anonymní uživatel
4014 příspěvků
20. 2. 2015   #29
-
0
-

jeste jedna vec, mozna. Proc tam provadis deleni? Nebude rychlejsi delit az tam, kde to pouzijes?

(*f1)[a][b]=1.0/(a-b); // delta: max / min
(*f2)[a][b]=(a-b)/a; // Saturation: delta / max

a kdyz uz tam delas deleni, nebylo by rychlejsi nasobeni a 1/a hodit pred ten cyklus na druhem radku?
z = 1/a;
zz = 1.0; // mozna i tu jednicku, ale tu asi neni treba
(*f1)[a][b]=zz / (a-b); // delta: max / min
(*f2)[a][b]=(a-b) * z; // Saturation: delta / max

V php treba pro cisla pouzivam zapisu 0xFF, kdyz chci 1 byte cislo a chci si byt jisty, ze mi tam nehodi integer. Nevim, jak se to dela v c++.

Nahlásit jako SPAM
IP: 2001:718:2601:1f7:10d7:56...–
20. 2. 2015   #30
-
0
-

#25 oxidián
celou dobu se ti snaží vysvětlit, že unsigned char nemůže nikdy přejít hodnotu 255. V případě, že budeš neustále inkrementovat, proměnná přeteče - stane se toto: .. 254 .. 255 .. 0 .. 1 .. char je vždy !! menší než 256 bez ohledu na to, zda signed nebo unsigned. Do 8 bitů se jednoduše víc nevejde. Cyklus řízený podmínkou a < 256 nebo a <= 255 (a je char nebo unsigned char) může být nekonečný. Je možné, že se implicitně provede přetypování na int a s ní cyklus pracuje. Každopádně bych se takové věci vyhnul. Optimalizace za každou cenu může vyjít docela draho - hodně zbytečného úsilí a času.

hu

Nahlásit jako SPAM
IP: 2001:67c:1222:800:e0c8:2b...–
oxidián0
Grafoman
20. 2. 2015   #31
-
0
-

Satik:

Asi zkusím jestli nezapomenu. Teď jsem řešil obecný algoritmus a chyby při zápisu do bmp. Ještě jsem ten algoritmus vylepšil, protože jsem tam našel jednu chybu, která tam původně nebyla ale tím jak jsem to přepisoval do C jsem si nevšiml, že pokud max=0 tak se neukládal výsledek.

Jak jsem už psal, nemohu používat celý čísla, je třeba přesnost aspoň na 5 desetinných míst. I tak je to nepřesné

Peter:

To už neřeš je to už vyřešený. musí tam být a++ ne ++a a musí to začínat 1 ne 0. Pro max 0 nepotřebuju počítat odstín, protože pro max=0 není definovaný.

Neprovádím tam stejnou operaci. malloc přiděluje paměť 2x ne 1x. Chci dva zásobníky ne jeden.

Jestli tam dám a-b nebo x je už jedno na rychlost to nemá vliv.

0+a-1 nemám to z nížek ale z vlastní hlavy, mohu zkusit ale předpokládám že rozdíl by byl v desetitisícinách.

Tak jsem to zkusil a měl jsem pravdu:

volání funkce bez změn v podmínce: 0.000831s

se změnou v podmínce: 0.000827 až 0.000828s

předpočítaný výsledek x=a-b  odpovídá 0.000809 až 0.000834s

A jelikož je to v desetisícinách tak to vůbec nehraje roli. Pakárna co akorád znepřehlední kód

Hluché ucho: Ta přezdívka ti opravdu moc hezky sedne, vzhledem k tomu že nevidíš že už to je dávno vyřešené a že se tu jen zbytečně opakujete.

Overscout:

Taky - unsigned short int a,b; versus int a,b; ušetřím 4 desetitisíciny, tak ty si klidně můžeš nechat :-)

Nevím co jsou to za optimalizace nikdy jsem to nepoužíval.

Pokud max==min pak se nepočítá s deltou ale s nulou (násobení, ne dělení)

Nahlásit jako SPAM
IP: 78.45.199.–
Satik0
Stálý člen
20. 2. 2015   #32
-
0
-

#31 oxidián

Jak jsem už psal, nemohu používat celý čísla, je třeba přesnost aspoň na 5 desetinných míst. I tak je to nepřesné

A kde je problém? 32bitová celá čísla umí ukládat přesnost na 9-10 řádů.

Třeba místo rozsahu 0f-1.0f bys používal 0-255 (pokud ti stačí 255 hodnot mezi 0-1) apod.

Převést výpočty s desetinnými čísly na celá je celkem běžná optimalizace (obzvlášť pokud vstup i výstup jsou celá čísla), případně jen ta data převedeš na začátku z desetinných na celá nabo na konci výpočtu z celých na desetinná. Ten vliv na rychlost bývá opravdu celkem znatelný.

Nahlásit jako SPAM
IP: 86.49.188.–
oxidián0
Grafoman
20. 2. 2015   #33
-
0
-

Satik: Potřeboval bych příklad, neumím si to z hlavy představit jak to funguje. Nechápu jak by mi mohlo stačit 255 hodnot, když pracuju s číslem např. 0.002777 což je obrácená hodnota z 360. Je tam 5 míst za desetinnou čárkou.

Edit: Já to fakt nechápu. Tak jediný převod, který mě napadá je vynásobit to 100000 ale to bych pak musel zase dělit tak bych snad nic nezískat? Dělení jsem se chtěl vyhnout protože je pomalejší.

Myslel jsem že na tom už nic zoptimalizovat nelze ale mezitím jsem vypustil další 4 zbytečné řádky.

Nahlásit jako SPAM
IP: 78.45.199.–
oxidián0
Grafoman
20. 2. 2015   #34
-
0
-

Vytvořil jsem si soubor bmp, rgb 24bit 16x16. Načtu hlavičku 54 byte, raster 770 byte (768 má obraz a dva bajty jsou na konci: 0000). Provedu rgb2hsv, zapíšu havičku 54 byte, zapíšu image 770 byte a mezeru 4 byte (0000). A nejde to otevřít. Má to stejný počet bytů i stejnou hlavičku a přesto to nejde. Nevíte v čem může být problém? Na malém obrázku 4x4 mi to fungovalo.

Nahlásit jako SPAM
IP: 78.45.199.–
Satik0
Stálý člen
23. 2. 2015   #35
-
0
-

#33 oxidián
Např. když počítáš alphablending mezi dvěma barvama (máš je jako unsigned char 0-255) a alphu máš jako float 0-1.0f tak můžeš buďto použít desetinný čísla a počítat takhle:

BYTE r = (BYTE)(r1*a + r2*(1-a));

a nebo si alphu posílat jako int 0-256 (kde 0 odpovídá nule a 256 odpovídá 1.0f) a pak takhle celočíselně:

BYTE r = (BYTE)((r1*a + r2*(256-a)) / 256);

(Případně můžeš to dělení 256 nahradit za << 8, ale se většina kompilátorů to udělá za tebe) nebo se tomu vypnout úplně a ten konec (dělení 256) rovnou přepsat do asm a vzít rovnou jen vyšší část registru - tam nevím, kolik kompilátorů to za tebe udělá.

Nahlásit jako SPAM
IP: 86.49.188.–
oxidián0
Grafoman
23. 2. 2015   #36
-
0
-

Tak to mi nic neříká, co je BYTE, r1, r2, a?

Když si už nadhodil ten alphablending tak ten mě moc zajímá. Ani jsem nevěděl jak se tomu říká, ale chtěl bych to později zkusit. Teď mi jde spíš o převody v barvových prostorech RGB-HSV-CMYK a histogram, threshold, levels, cubic splines. Taky bych chtěl dělat ten alphablending ale s tím že bych tam chtěl nějaký efekt jako je ve Photohopu: soft light, hard light, darken, linear light, color dodge, multiply, atd. Nevím jak moc to bude těžké, ale daj se na toto téma najít nějaké články? Jelikož se tomu aktuálně nevěnuju tak nehledám, ale jestli o něčem víš tak dej vědět protože algoritmy se mi budou hodit.

Psát v asm bohužel neumím. Trochu mi to přibliž o co jde.

Mě ještě zajímá jestli se dají nějak urychlit operace když děláš takový ty převody mezi typy jako char na integer nebo integer zapsaný v souboru a jak to načítáš tak to převádíš do little endian (moje x86) tak aby se to nepsalo na 4 řádky a 4 přiřazování, ale jen jeden řádek a jedno přiřazování jestli něco takového jde. Protože mě přijde, že když se něco zbytečně přiřazuje 4x tak se zbytečně odesílají data do cache (je to pomalejší), ale nešlo by to nějak účinněji udělat aby to člověk nejdříve spočítal na jednom řádku a pak to odeslal někam do cache tím přiřazením hodnoty proměnné?

Nahlásit jako SPAM
IP: 78.45.199.–
Satik0
Stálý člen
23. 2. 2015   #37
-
0
-

BYTE je obvykle unsigned char - proměnná s rozsahem 0-255

r1 r2 byly myšleny hodnoty červeného kanálu blendovaných pixelů, a alpha

alphablending je prolnutí dvou obrázků v určitém poměru, o žádných článcích takhe z hlavy nevím, takže google :)

Ty kejkle s asm něco urychlit můžou, ale ten vliv tam už reálně nebude většinou ani měřitelný :) 

Jinak délka kódu nemá na rychlost programu žádný vliv, hlavní je, co z toho pak vyleze za instrukce, ale to už je dost alchymie a obvykle je lepší do toho nehrabat, pokud si opravdu nejseš jistý, co děláš :) .

Na změnu endianu určitě na googlu budou nějaké rychlé funkce, určitě i přímo v asm, stačí pohledat.

Nahlásit jako SPAM
IP: 77.87.240.–
oxidián0
Grafoman
24. 2. 2015   #38
-
0
-

Ještě jednou ti mohu potvrdit, že pokud máš cyklus 4096*4096, tak každý jeden přiřazovací příkaz navíc je časově znát, na mé x86 2,96 GHz je to cca 0.01s na jeden přiřazovací příkaz pokud jich odstraníš víc a nahradíš to jinak, tak se ti program/funkce/smyčka může urychlit klidně o 0.1 s.

Nahlásit jako SPAM
IP: 78.45.199.–
Satik0
Stálý člen
24. 2. 2015   #39
-
0
-

To zalezi i na tom, odkud kam se co hybe a jestli je tam zavislost - napr. pokud se neco nacita z pameti do registru a pak hned ten registr pouzivas, tak si chvili pockas (obzvlast, pokud to neni v procesorovy cache).

Jeden mov z registru do registru uz by v tomhle pripade (treba ten alphablending) byl nejspis na hranici meritelnosti, vetsinu casu  nejspis sezere cteni/zapis do pameti a pak ta matematika.

Samozrejme hlavni je to otestovat v realu (v release modu, se zapnutymi optimalizacemi a mimo vyvojove prostredi).

Nahlásit jako SPAM
IP: 86.49.188.–
peter
~ Anonymní uživatel
4014 příspěvků
24. 2. 2015   #40
-
0
-

Literatury je na netu fura, ale vetsinou teorie nebo matematika. Coz je pro programovani naprosto nevhodny zapis :)
S modely jsem si hral tady, ale nini to c++ a neni to optimalizovane na rychlost.
http://peter-mlich.wz.cz/…s-color4.htm
(v prohlizeci jde zobrazit zdrojovy kod JS)
Slo mi o to, ze kdyz zadam nejakou barvu, tak z ni vytahnu hsl model a pouziji ho pro jinou barvu. to resi ta tabulka vpravo nahore (treba, jak mam 6xA, zadas tam barvu, treba 5AEFB6 a on ti podle ni nastinuje cely radek - to se mi strasne hodi pro delani webu v ruznych barvach). Tabulka dole resi zas nejake jine veci, co sem nasel na netu. krasne tam je videt treba chyba hsl gradientu, ze mi misto prechodu cervena-fialova vygeneroval barvy duhy :) To je podle mne nejaky problem v tom kodu, co jsem nasel.

Tim ti chtel naznacit, ze vypocet promenne r (barva_vysledek-red) jako byte (cislo 0-255) z cisel r1 a r2 (barva1-red a barva2-red) muzes udelat takto
BYTE r = (BYTE)(r1*a + r2*(1-a)); // "a" mas definovane jako 0.00-1.00 (0-100%) a nebo
BYTE r = (BYTE)((r1*a + r2*(256-a)) / 256); // tady nebude dochazet k prevodu "a", protoze si "a" definujes jako  0-255, ale zas ti to muze zpomalit to deleni :)
BYTE r = (BYTE)((r1*a + r2*b) / 256) // kde pocitam ab takto: a = 256, b = 0, a--, b++, to by mohlo byt rychlejsi nez odcitani

Prelozeno do cestiny, kdyz delas prechod barev, tak pocitas
barva = 70% barva1 + 30% barva2

Totez delas u tech modelu hsv nebo yuv
h = 29.9% red + 58.7% green , 11.4% blue

Nahlásit jako SPAM
IP: 2001:718:2601:1f7:2402:38...–
peter
~ Anonymní uživatel
4014 příspěvků
24. 2. 2015   #41
-
0
-

Jo, mimochodem, jestli delas nejaky spesl program a ne neco do skoly, zkus tam zamontovat spesl doostrovani, na ktere jsem prisel nedavno v Gimpu :)

vrstvy 3 2 1
1 dupl 2
2 ostreni 80%
2 kryti 50% slouceni zrnitosti
3 kryti 50% jas

Nevim, jak se matematicky pocita ostrani a slouceni zrnitosti. Vubec, kterej pip to prekladal do cestiny, kdyz v anglictine to je uplne jasny pojem a snadno dohledatelny i navody v anglictine :)

Nahlásit jako SPAM
IP: 2001:718:2601:1f7:2402:38...–
oxidián0
Grafoman
24. 2. 2015   #42
-
0
-

Zajímavá JS aplikace. Ještě se sem vrátím až bude čas, teď je toho moc takže nestíhám. Člověk by nejraději dělal tři věci najednou, ale to bohužel nejde.

Nahlásit jako SPAM
IP: 78.45.199.–
Zjistit počet nových příspěvků

Přidej příspěvek

Toto téma je starší jak čtvrt roku – přidej svůj příspěvek jen tehdy, máš-li k tématu opravdu co říct!

Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku

×Vložení zdrojáku

×Vložení obrázku

Vložit URL obrázku Vybrat obrázek na disku
Vlož URL adresu obrázku:
Klikni a vyber obrázek z počítače:

×Vložení videa

Aktuálně jsou podporována videa ze serverů YouTube, Vimeo a Dailymotion.
×
 
Podporujeme Gravatara.
Zadej URL adresu Avatara (40 x 40 px) nebo emailovou adresu pro použití Gravatara.
Email nikam neukládáme, po získání Gravatara je zahozen.
-
Pravidla pro psaní příspěvků, používej diakritiku. ENTER pro nový odstavec, SHIFT + ENTER pro nový řádek.
Sledovat nové příspěvky (pouze pro přihlášené)
Sleduj vlákno a v případě přidání nového příspěvku o tom budeš vědět mezi prvními.
Reaguješ na příspěvek:

Uživatelé prohlížející si toto vlákno

Uživatelé on-line: 0 registrovaných, 86 hostů

Podobná vlákna

Bitmapy — založil david

ZObrazeni bitmapy — založil _Radek_

Uloženie dát do Bitmapy — založil Peter

Vykreslení Bitmapy do lišty — založil Mutagen

Moderátoři diskuze

 

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032024 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý