C++, použití free()

gamer

Re:C++, použití free()
« Odpověď #30 kdy: 05. 09. 2013, 20:25:26 »
boost multi array má úplně stejný výkon jako nativní implementace. Není důvod to nepoužít.

Nativně:
Kód: [Vybrat]
#include <iostream>

int main()
{
    const int SIZE = 10;
    double array[SIZE][SIZE][SIZE];

    for (int i = 0; i < SIZE; ++i)
        for (int j = 0; j < SIZE; ++j)
            for (int k = 0; k < SIZE; ++k)
                array[i][j][k] = i + j + k;

    double result = 0.0;
    for (int a = 0; a < 1000000; ++a)
        for (int i = 0; i < SIZE; ++i)
            for (int j = 0; j < SIZE; ++j)
                for (int k = 0; k < SIZE; ++k)
                    result += array[i][j][k];

    std::cout << "result: " << result << std::endl;

    return 0;
}

Výsledky nativního pole:
Kód: [Vybrat]
g++ -s -O3 native.cc -o native
du -bs native
7760 native
time ./native
result: 1.35e+10

real 0m1.190s
user 0m1.172s
sys 0m0.020s

multi_array:
Kód: [Vybrat]
#include <iostream>
#define BOOST_DISABLE_ASSERTS
#include <boost/multi_array.hpp>

int main()
{
    const int SIZE = 10;
    typedef boost::multi_array<double, 3> array_type;
    typedef array_type::index index;
    array_type array(boost::extents[SIZE][SIZE][SIZE]);

    for (index i = 0; i < SIZE; ++i)
        for (index j = 0; j < SIZE; ++j)
            for (index k = 0; k < SIZE; ++k)
                array[i][j][k] = i + j + k;

    double result = 0.0;
    for (int a = 0; a < 1000000; ++a)
        for (index i = 0; i < SIZE; ++i)
            for (index j = 0; j < SIZE; ++j)
                for (index k = 0; k < SIZE; ++k)
                    result += array[i][j][k];

    std::cout << "result: " << result << std::endl;

    return 0;
}

Výsledky multi_array:
Kód: [Vybrat]
g++ -s -O3 multi.cc -o multi
du -bs multi
8984 multi
time ./multi
result: 1.35e+10

real 0m1.175s
user 0m1.168s
sys 0m0.008s

multi_array je úplně stejně rychlé jako nativní pole a kód je o 1224 bajtů větší (to je opravdu hrozná režie...). Naopak implementace pomocí *** bude mnohem pomalejší a paměťově náročnější, zbytečně se tam několikrát provádí dereference a pamět není alokovaná v souvislém bloku, což způsobuje více cache misses a cache trashing. Ještě nějaké argumenty proti boostu a multi_array?


Martin

Re:C++, použití free()
« Odpověď #31 kdy: 05. 09. 2013, 22:44:15 »
Hlavně se ohánět efektivitou. Pár pointerů navíc, čert je vem, pokud ti nejde o "každý bajt". Horší je ten milión dereferencí, když máš plnej procesor násobiček, který leží ladem.
Kód: [Vybrat]
#define pole(x, y, z) __pole[x*ix*iy+y*iy+z]
__pole = malloc(ix*iy*iz*sizeof(double));
...
free(__pole);
Bez boostu, přehledně, rychle a jednoduše ;)
(Nemaťte mě za chybějící závorky v makru, vynechal jem pro přehlednost.)

Zmlátíme tě za používání maker v C++.

DK

Re:C++, použití free()
« Odpověď #32 kdy: 06. 09. 2013, 00:34:56 »
gamer: to s *** neni vubec pravda... ve skutecnosti to bude o krapet rychlejsi, vyzkousej s -O3 toto
Kód: [Vybrat]
#include <iostream>
#include <cstdlib>

int main(){
  const int SIZE = 10;
  double *** pole = (double ***) malloc(SIZE*sizeof(double**));

  for(int i=0;i<SIZE;i++){
    pole[i] = (double **) malloc(SIZE*sizeof(double *));
    for(int j=0;j<SIZE;j++){
        pole[i][j] = (double *) malloc(SIZE*sizeof(double));
        for(int k=0;k<SIZE;k++){
          pole[i][j][k] = i+j+k;
        }
    }
  }

  double result = 0.0;
  for(int a=0;a<1000000;a++){
    for(int i=0;i<SIZE;i++){
      for(int j=0;j<SIZE;j++){
        for(int k=0;k<SIZE;k++){
          result += pole[i][j][k];
        }
      }
    }
  }

  std::cout << "result: " << result << std::endl;

  for(int i=0;i<SIZE;i++){
    for(int j=0;j<SIZE;j++){
        free(pole[i][j]);
    }
    free(pole[i]);
  }
  free(pole);

  return 0;
}

u me to jede o par desitek milisekund rychleji nez nativni ci boost implementace (ty jsou rychlostne asi na stejne urovni)

prezek

  • ***
  • 229
    • Zobrazit profil
Re:C++, použití free()
« Odpověď #33 kdy: 06. 09. 2013, 09:02:29 »
Kód: [Vybrat]
#include "stdafx.h"
#include <time.h>
#define MULTI_ARRAY

#ifndef MULTI_ARRAY
#include "malloc.h"
#else
#include "boost/multi_array.hpp"
#endif
#include <cassert>

void fce() {
    int ni = 3, nj = 4, nk = 2;
#ifdef MULTI_ARRAY
    // Create a 3D array that is 3 x 4 x 2
    typedef boost::multi_array<double, 3> array_type;
    typedef array_type::index index;
    array_type A(boost::extents[ni][nj][nk]);
    index i, j, k;
#else

    double ***A;
    int i, j, k;
    A = (double***) malloc(ni * sizeof (double**));
    for (i = 0; i < ni; i++) {
        A[i] = (double**) malloc(nj * sizeof (double*));
        for (j = 0; j < nj; j++)
            A[i][j] = (double*) malloc(nk * sizeof (double));
    }
#endif
    // Assign values to the elements
    int values = 0;
    for (i = 0; i != 3; ++i)
        for (j = 0; j != 4; ++j)
            for (k = 0; k != 2; ++k)
                A[i][j][k] = values++;
    // Verify values
    int verify = 0;
    for (i = 0; i != 3; ++i)
        for (j = 0; j != 4; ++j)
            for (k = 0; k != 2; ++k)
                assert(A[i][j][k] == verify++);



#ifdef MULTI_ARRAY
#else
    for (i = 0; i < ni; i++) {
        for (j = 0; j < nj; j++)
            free(A[i][j]);
        free(A[i]);
    }
    free(A);
#endif
}

int _tmain(int argc, _TCHAR* argv[]) {
    time_t t0 = time(NULL);
    for (int i = 0; i < 500000; i++)fce();
    time_t t1 = time(NULL);
    printf("%d %d %d", (int) t0, (int) t1, (int) (t1 - t0));
    return 0;
}
Testováno Microsoft Visual Studio C++:
multi_array 28s
*** 5s
Jestli někomu vyjde multi_array rychlejší než *** s výrazným časovým rozdílem, tak dejte vědět.

PS: Ještě pořád nevím, co je špatného na "double ***A;", prosím o vysvětlení.

gamer

Re:C++, použití free()
« Odpověď #34 kdy: 06. 09. 2013, 09:27:52 »
Zapomněl jsi na BOOST_DISABLE_ASSERTS, když to nenadefinuješ, dělá multi_array range checking. Přistup přes pointery bude výrazně pomalejší, pokud se to pole nevejde to cache. n-násobená dereference každá znamenající cache miss je zabiják výkonu.


DK

Re:C++, použití free()
« Odpověď #35 kdy: 06. 09. 2013, 10:21:50 »
prezek: s define MULTI_ARRAY a BOOST_DISABLE_ASSERTS (velikost 10384)
Kód: [Vybrat]
1378455254 1378455254 0
real 0m0.064s
user 0m0.056s
sys 0m0.004s

s define MULTI_ARRAY (velikost 14504)
Kód: [Vybrat]
1378455308 1378455308 0
real 0m0.060s
user 0m0.056s
sys 0m0.000s

bez define MULTI_ARRAY (velikost 10376)
Kód: [Vybrat]
1378455345 1378455345 0
real 0m0.340s
user 0m0.336s
sys 0m0.000s

vse kompilovano pod linuxem pres g++ 4.7.3 s O3


tak nam tady vysvetlete, jak je pouziti boostu nevhodne a ba primo kontraproduktivni... u vetsich poli a vetsich dat je *** mirne rychlejsi (viz muj predchozi test), nicmene ve vasem prikladu je temer 6x pomalejsi
argumentace tim, ze to kompilujete ve visual studiu neberu... dle vasich slov bojujete o kazdy byte


a propos, stdafx je proprietarni knihovna pro windows, vyborne na multiplatformni aplikace... a je vazne videt, ze programovat moc neumite, jinak byste vyuzil ty ni,nj a nk promenne

JSH

Re:C++, použití free()
« Odpověď #36 kdy: 06. 09. 2013, 11:23:50 »
Testováno Microsoft Visual Studio C++:
multi_array 28s
*** 5s
Můžu se zeptat, jakou verzi Visual Studia a jaké nastavení překladače jsi použil? Ty časy jsou dost zoufalé. Hlavně by mě zajímalo nastavení optimalizací (/O...) a runtime testů (/RTC...).

Tohle totiž vypadá, že je vypnutý inlining a jsou zapnuté runtime testy zásobníku. To pak překladač každou funkcičku obalí dost náročným "balastem". Ty časy by tomu odpovídaly.

JSH

Re:C++, použití free()
« Odpověď #37 kdy: 06. 09. 2013, 11:44:48 »
Tak to je jasny, to kvuli tobe ma pak "hello world" 50MB ...
A kolik by měl takový hello world mít? Počítá se do té velikosti jen exe, nebo i C++ runtime knihovny (nebo jinéo jazyka), systémové knihovny a podobně?

Opravdu má cenu osekávat pár bytů z kódu programu, když pak u toho programu bude několik set megabyte dat? Když máme disky v terabytech, paměť v gigabytech a platí pravidlo 90/10?

Mimochodem, srovnavas nesrovnatelny, java, php ... nejsou kompilovany jazyky.
Java je kompilovaný jazyk. Kompiluje se napřed do bytekódu a při běhu se ten bytekód kompiluje na instrukce procesoru. A než namítneš, že je to něco jiného, tak C++ se kompiluje podobně. Jen se ten "bytekód" neukládá.

Zlaty lidi, co jeste dneska umej delat 64kB demace ...
Kolik dem už jsi napsal? Protože tímhle způsobem ušetříš +-prd. U dem jsou důležité věci jako procedurální generování geometrie/obrazu/zvuku. Vyhýbat se header-only knihovnám z boostu je kravina.

prezek

  • ***
  • 229
    • Zobrazit profil
Re:C++, použití free()
« Odpověď #38 kdy: 06. 09. 2013, 12:50:51 »
prezek:
... a je vazne videt, ze programovat moc neumite, jinak byste vyuzil ty ni,nj a nk promenne
Můžu se zeptat, jakou verzi Visual Studia a jaké nastavení překladače jsi použil? Ty časy jsou dost zoufalé. Hlavně by mě zajímalo nastavení optimalizací (/O...) a runtime testů (/RTC...).

Já říkal, že "neumím pořádně programovat"... :)
Chtěl jsem jen prověřit, že boost je blbost (tam, kde se dá nahradit *** a 6 řádky programu navíc) a po cca 10 minutách jsem viděl výsledek, který mě uspokojil. To, že ten výsledek neodpovídal realitě mi nevadilo. S nastavováním optimalizace jsem si hlavu nelámal a použil defaultní při založení nového projektu. Teď jsem zkusil jen přepnout profil debug(/Od) na release(/O2) a výsledek se otočil. Přesvědčili jste mě, boost zřejmě má smysl ve většině případů a třeba ho někdy taky využiju. Takže díky.

Sten

Re:C++, použití free()
« Odpověď #39 kdy: 06. 09. 2013, 13:38:11 »
Java je kompilovaný jazyk. Kompiluje se napřed do bytekódu a při běhu se ten bytekód kompiluje na instrukce procesoru. A než namítneš, že je to něco jiného, tak C++ se kompiluje podobně. Jen se ten "bytekód" neukládá.

GIMPLE či LLVM IR jsou podobné JVM asi tak jako Céčko Fortranu. Navíc JVM je na rozdíl od těch dvou stack-based, což dost ztěžuje kompilaci a kvůli tomu to má často mizerný výkon. Proto Dalvik v Androidu používá register-based bajtkód. Takže ano, oboje používá bajtkód, ale úplně jiný a úplně jinak.