Elektroda.pl
Elektroda.pl
X

Search our partners

Find the latest content on electronic components. Datasheets.com
Elektroda.pl
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

new/delete - malloc/free - co lepsze do wielkich dyn. tablic?

lukagrom 11 Sep 2018 10:48 384 12
  • #1
    lukagrom
    Level 16  
    Witam. Pytanie jak w temacie. Potrzebuje "podziałać" na dużych tablicach tworzonych dynamicznie i pózniej usuwanych. Czy jest jakaś znacząca różnica w oszczędzaniu pamięci i czasie realizacji operacji w wykorzystaniu instrukcji new/delete i malloc(lub jego klony)/free?
  • #2
    JacekCz
    Level 39  
    adekwatnie do języka, gdzie C to C, gdzie C++ to C++
  • #4
    lukagrom
    Level 16  
    Podobno w starych czasach, gdy moc obliczeniowa nie była największa i algorytmika, miała spore znaczenie na czas realizacji programu, to w kwestii wykorzystania pamięciożernych operacji na dynamicznych tablicach czy strukturach, było zapatrywanie by robić coś takiego w C z użyciem malloc/free, pewnie nadal tak jest, jednakże przy współczesnej technologii i mocy para dla C++ new/delete już nie jest wypasioną ekstrawagancją i pewnie nie ma to już żadnego znaczenia, zwłaszcza że powstały już nowe operatory dynamicznego tworzenia jak np gcnew dla Visual C++, który zwalnia pamięć, dopiero po zakończeniu działania programu, więc powyższe "rozterki oszczędnościowe" dla dzisiejszej mocy obliczeniowej to tylko pewnie płytka dywagacja.
  • #5
    Dżyszla
    Level 42  
    Jeśli rezerwujesz pamięć raz, dwa podczas operacji to stawia się na wygodę. Ale jeśli będziesz musiał to robić milion razy, to czynniki wydajnościowe mogą być istotniejsze i schodzi się do niższego poziomu, jeśli jest on bardziej wydajny, nawet kosztem większej trudności zaprojektowania i utrzymania kodu.
  • #6
    JacekCz
    Level 39  
    lukagrom wrote:
    Podobno w starych czasach, gdy moc obliczeniowa nie była największa i algorytmika, miała spore znaczenie na czas realizacji programu, to w kwestii wykorzystania pamięciożernych operacji na dynamicznych tablicach czy strukturach, było zapatrywanie by robić coś takiego w C z użyciem malloc/free, pewnie nadal tak jest, jednakże przy współczesnej technologii i mocy para dla C++ new/delete już nie jest wypasioną ekstrawagancją i pewnie nie ma to już żadnego znaczenia, zwłaszcza że powstały już nowe operatory dynamicznego tworzenia jak np gcnew dla Visual C++, który zwalnia pamięć, dopiero po zakończeniu działania programu, więc powyższe "rozterki oszczędnościowe" dla dzisiejszej mocy obliczeniowej to tylko pewnie płytka dywagacja.


    1. możesz użyć interpunkcji?
    2. Nie ma operatora gcnew w języku C++. Nie siej zamętu. Za to jest, coraz bardziej outdated, język C++/CLI, który jest wzorowany/posiada elementy C++ i jest przeznaczony do środowiska zarządzalnego, jako ubogi krewny C#
    3. Nie mieszaj innych modeli gospodarki pamięcią (choć takie oczywiście są) do C/C++, pytanie jest bardzo seletywne
    4. Program w konwencji C/C++ tez nie w 99.9% zwraca pamięci do systemu

    Dodano po 11 [minuty]:

    Dżyszla wrote:
    Jeśli rezerwujesz pamięć raz, dwa podczas operacji to stawia się na wygodę. Ale jeśli będziesz musiał to robić milion razy, to czynniki wydajnościowe mogą być istotniejsze i schodzi się do niższego poziomu, jeśli jest on bardziej wydajny, nawet kosztem większej trudności zaprojektowania i utrzymania kodu.


    Plotki i pogłoski w/s wydajności ... tak sobie znajdują potwierdzenie w życiu. Jest sobie taki serwer Apache Qpid, który ma dwie implementacje, C++ oraz w języku zarządzalnym, w tym wypadku Java. I tu miejsce na zagadkę: który jest bardziej wydajny?
    (mam świadomość że odczucie wydajności trzeba zdefiniować : throughput, latency, miara centylowa i inne miary)


    EDIT: nie należy w kodzie C++ używać malloc/free, choć pewnie 100x będzie działać, a 101szy wdeptujemy na minę.
  • #7
    Dżyszla
    Level 42  
    JA cały czas pozostaję w kontekście przeprowadzenia realnych testów wydajnościowych, jeśli na tym bardzo autorowi zależy i zwracam uwagę, że może to być kompletnie nieopłacalne. Nie stwierdziłem, że alokacja pamięci w ten czy inny sposób jest szybsza lub mniej, natomiast generalnie często (acz nie zawsze) im wyższy stopień abstrakcji tym wolniej. Niemniej sam kompilator potrafi wnieść bardzo dużo w wydajność i zdecydowanie postępy są w tym zakresie nawet bez potrzeby jakiejkolwiek zmiany kodu. Dlatego w jednym środowisku (kompilatorze) użycie new zajmie x czasu, a w innym 2x tyle.

    Odrębną kwestią jest, że np gotowe funkcje umieszczane w bibliotekach są optymalizowane. Jedna i ta sama kiedyś mogła być powolna, w kolejnej wersji mogła wykorzystywać szybszą wersję z WinAPI a w jeszcze kolejnej ktoś doszedł do wniosku, że najlepiej to napisać w asemblerze. Dlatego na takie pytania zawsze odpowiadam - sprawdź sam, jak zachowuje się to w Twoim środowisku i miej na uwadze, że kod, który skompilowany jednym kompilatorem działa szybko, pod innym może działać wolniej, a ogólną zasadą jest jednak patrzenie w stronę nowych rozwiązań.
  • #8
    JacekCz
    Level 39  
    Dżyszla wrote:
    JA cały czas pozostaję w kontekście przeprowadzenia realnych testów wydajnościowych


    Skrócę, a skracając Twoją wypowiedź przerysowuję. Chcesz testem wydajnościowym potwierdzić która z dwóch konstrukcji prawidłowa / nieprawidłowa (nielegalna) .... która jest właściwa?

    Nalezy używać prawidłowej dla języka. Po jego wybraniu można mówić o (mikro czy rzeczywistych)optymalizacjach. Zwykle wybór dobrego algorytmu daje 100-1000x lepszy zysk niz mikro-optymalizacje.
  • #9
    Dżyszla
    Level 42  
    Nie do końca się zgodzę z tym ostatnim stwierdzeniem. Dużo poświęciłem tematowi optymalizacji kodu bez zmiany algorytmu i naprawdę można osiągnąć znaczące zmiany. Poza tym co w momencie, gdy algorytm jest już najlepszy, ale jego implementacja kuleje? Pewnie - gdy ktoś zna zasady to już w pierwszym podejściu zaimplementuje algorytm wydajnie (choć należałoby powiedzieć: przyjaźnie dla kompilatora) także od strony sposobu zapisu kodu. Ale czasem można znaleźć jeszcze potencjał właśnie w modyfikacjach kodu bez zmiany algorytmu. Owszem - algorytm to podstawa. Ale nie koniec w procesie optymalizacji wydajności.

    Co do "nielegalności" używania malloc - owszem, new znacznie ułatwia pisanie i uniemożliwia popełnienie błędu. Ale jeśli ktoś wie, co robi, to da się używać malloc (co zaznaczałem też wcześniej). Chyba, że mnie zaskoczysz jakąś informacją, dlaczego jest to nieprawidłowe (zakładając, że programista dobrze wie, co robi).
  • #10
    JacekCz
    Level 39  
    Code: c
    Log in, to see the code


    Jakie (przynajmniej) dwa problemy ma ten kod?
  • #11
    Dżyszla
    Level 42  
    Pewnie, do klas to się nie nadaje. To osobny wątek i w zasadzie w ten sposób obiektów tworzyć faktycznie się nie powinno. Ale kolega mówił o tablicach, domyślam się że typów prostych, a nie obiektów. I ja też w tym kręgu pozostaję.
  • #12
    _lazor_
    Moderator of Designing
    W sieci jest trochę na ten temat napisanych już rzeczy.

    https://www.geeksforgeeks.org/malloc-vs-new/
    https://stackoverflow.com/questions/184537/in-what-cases-do-i-use-malloc-vs-new

    Jeśli piszesz w C++ łącznie z wszystkimi jego feature (exeption handling, RTTI, STL, boost itp) to myślę, że uzyskanie performance na alokowaniu pamięci nie będzie zbytnio dużym uzyskiem.
    Dodatkowo C++ prostym językiem nie jest i nie koniecznie new jest jednoznaczne, bo można go użyć w wieloraki sposób:
    http://www.cplusplus.com/reference/new/operator%20new/

    I tak możesz użyć kombinacji przykładu 2 i 4 i masz prawie to sam co malloc :D
  • #13
    ble___
    Level 15  
    Jak zależy na czasie alokacji to chyba można tego nie robić w razie potrzeby tylko raz na początku i/lub większymi porcjami.

    Operatory new/delete czy inne f. chyba mogą robić różne rzeczy w zależności od implementacji i można je czasem samemu podmienić.

    Chyba zawsze musi zostać użyte API systemu operacyjnego (jeśli użyty jest tryb chroniony procesora) więc rozsądniejsze wydaje się porównanie sposobów udostępnianych przez dany system np.
    https://docs.microsoft.com/en-us/windows/desktop/memory/comparing-memory-allocation-methods
    czy w Linuks chyba brk czy mmap się używa.

    Testy konkretnej sytuacji mogą coś powiedzieć.
    Niektóre środowiska używają domyślnie pooling'u i wywołanie "new" może zwrócić zaalokowaną dużo wcześniej pamięć.