Wysoce wydajny C++. Opanuj sztukę optymalizowania działania kodu. Wydanie 2 - ebook
Wysoce wydajny C++. Opanuj sztukę optymalizowania działania kodu. Wydanie 2 - ebook
Dzisiejszy C++ jest wyjątkowym językiem programowania. Umożliwia pisanie zwięzłego, stabilnego kodu, który można zoptymalizować pod kątem wydajności w niespotykanym dotychczas stopniu. Język C++ w ciągu ostatnich lat został unowocześniony. W standardzie C++ 20 znalazło się sporo mechanizmów, które pozwalają osiągnąć wysoką efektywność kodu, a równocześnie uprzyjemniają programiście pracę. Poprawiono także ustawienia domyślne kompilatora. To wszystko sprawia, że wielu profesjonalistów wybiera właśnie C++, gdy chce uzyskać kod o wyjątkowej wydajności.
Ta książka jest drugim, zaktualizowanym i uzupełnionym wydaniem przewodnika dla programistów. Rozpoczyna się od szczegółowego wprowadzenia do nowoczesnego C++ z uwzględnieniem technik eliminowania wąskich gardeł w kodzie bazowym. Następnie omówiono zagadnienia optymalizacji struktur danych i zarzadzania pamięcią. Przedstawiono również tematykę algorytmów, zasady pisania czytelnego kodu i stosowania niestandardowych iteratorów. Zamieszczono w niej też praktyczne przykłady używania metaprogramowania w języku C++, korutyn, refleksji (do ograniczenia ilości szablonowego kodu), obiektów pośredniczących (do wprowadzania ukrytych optymalizacji), programowania współbieżnego i struktur danych wolnych od blokad. W końcowej części dokonano przeglądu algorytmów równoległych w C++.
W książce między innymi:
- nowe aspekty C++ 20
- wyspecjalizowane struktury danych na potrzeby wydajnego kodu
- metaprogramowanie i niestandardowe zarządzanie pamięcią
- mechanizm refleksji i programowanie współbieżne bez używania blokad
- subtelne optymalizacje algorytmów z biblioteki standardowej C++
- leniwe generatory i zadania asynchroniczne
Twórz wydajny i czysty kod w C++!
Spis treści
Przedmowa
O autorach
O korektorach merytorycznych
Wprowadzenie
- Dla kogo przeznaczona jest ta książka?
- Zawartość książki
- Jak najlepiej skorzystać z tej książki?
- Pobieranie plików z przykładowym kodem
- Stosowane konwencje typograficzne
Rozdział 1. Krótkie wprowadzenie do języka C++
- Dlaczego C++?
- Bezkosztowe abstrakcje
- Przenośność
- Odporność
- Język C++ dzisiaj
- Porównanie C++ z innymi językami
- Konkurencyjne języki i wydajność
- Mechanizmy języka C++ niezwiązane z wydajnością
- Wady języka C++
- Biblioteki i kompilatory używane w tej książce
- Podsumowanie
Rozdział 2. Podstawowe techniki języka C++
- Automatyczne wykrywanie typów za pomocą słowa kluczowego auto
- Stosowanie słowa kluczowego auto w sygnaturach funkcji
- Stosowanie słowa kluczowego auto dla zmiennych
- Semantyka przenoszenia
- Tworzenie przez kopiowanie, wymienianie i przenoszenie
- Pozyskiwanie zasobów i reguła pięciu
- Zmienne nazwane i r-wartości
- Domyślna semantyka przenoszenia i reguła zera
- Stosowanie modyfikatora && do funkcji składowych klas
- Nie przenoś obiektów, jeśli kopiowanie i tak jest pomijane
- Jeśli to możliwe, stosuj przekazywanie przez wartość
- Projektowanie interfejsów z obsługą błędów
- Kontrakty
- Obsługa błędów
- Obiekty funkcyjne i wyrażenia lambda
- Podstawowa składnia lambd w języku C++
- Klauzula przechwytywania
- Przypisywanie do lambd wskaźników do funkcji języka C
- Typy lambd
- Lambdy i typ std::function
- Generyczne lambdy
- Podsumowanie
Rozdział 3. Analizowanie i pomiar wydajności
- Złożoność asymptotyczna i notacja dużego O
- Tempo wzrostu
- Zamortyzowana złożoność czasowa
- Co mierzyć i w jaki sposób?
- Aspekty wydajności
- Przyspieszanie wykonywania kodu
- Liczniki wydajności
- Testy wydajności - dobre praktyki
- Poznaj kod i znajdź hot spoty
- Profilery z instrumentacją
- Profilery z próbkowaniem
- Mikrotesty
- Prawo Amdahla
- Pułapki związane z mikrotestami
- Przykład ilustrujący mikrotesty
- Podsumowanie
Rozdział 4. Struktury danych
- Cechy pamięci w komputerach
- Kontenery z biblioteki standardowej
- Kontenery sekwencyjne
- Kontenery asocjacyjne
- Adaptery kontenerów
- Używanie widoków
- Unikanie kopiowania dzięki typowi string_view
- Unikanie utraty informacji o długości tablic dzięki typowi std::span
- Uwagi na temat wydajności
- Zapewnianie równowagi między gwarancjami złożoności a dodatkowymi kosztami
- Znajomość i stosowanie odpowiednich funkcji API
- Tablice równoległe
- Podsumowanie
Rozdział 5. Algorytmy
- Wprowadzenie do algorytmów z biblioteki standardowej
- Ewolucja algorytmów z biblioteki standardowej
- Rozwiązywanie codziennych problemów
- Iteratory i zakresy
- Wprowadzenie do iteratorów
- Wartość wartownika i iteratory zakońcowe
- Zakresy
- Kategorie iteratorów
- Cechy algorytmów standardowych
- Algorytmy nie zmieniają wielkości kontenera
- Algorytmy zwracające dane wyjściowe wymagają zaalokowanych danych
- Algorytmy domyślnie używają funkcji operator==() i operator<()
- W algorytmach z ograniczeniami używane są projekcje
- Algorytmy wymagają, aby operatory przenoszące nie zgłaszały wyjątków
- Algorytmy mają gwarantowaną złożoność
- Algorytmy działają równie dobrze jak analogiczne funkcje z bibliotek języka C
- Pisanie i stosowanie algorytmów generycznych
- Algorytmy niegeneryczne
- Algorytmy generyczne
- Struktury danych, które mogą być używane przez algorytmy generyczne
- Dobre praktyki
- Stosowanie algorytmów z ograniczeniami
- Sortowanie tylko tych danych, które będą pobierane
- Stosowanie algorytmów standardowych zamiast surowych pętli for
- Unikanie tworzenia kopii kontenera
- Podsumowanie
Rozdział 6. Zakresy i widoki
- Powody powstania biblioteki Ranges
- Ograniczenia biblioteki Algorithm
- Widoki z biblioteki Ranges
- Widoki można łączyć w łańcuch
- Widoki zakresów i adaptery zakresów
- Widoki są zakresami bez własności elementów oferującymi gwarancje złożoności
- Widoki nie modyfikują podstawowego kontenera
- Widoki można materializować do postaci kontenerów
- Widoki są przetwarzane leniwie
- Widoki z biblioteki standardowej
- Widoki dla zakresów
- Jeszcze o typach std::string_view i std::span
- Przyszłość biblioteki Ranges
- Podsumowanie
Rozdział 7. Zarządzanie pamięcią
- Pamięć w komputerze
- Wirtualna przestrzeń adresowa
- Strony pamięci
- Migotanie
- Pamięć procesu
- Pamięć na stosie
- Pamięć na stercie
- Obiekty w pamięci
- Tworzenie i usuwanie obiektów
- Wyrównanie pamięci
- Dopełnienie
- Własność pamięci
- Pośrednie zarządzanie zasobami
- Kontenery
- Inteligentne wskaźniki
- Optymalizacja małych obiektów
- Niestandardowe zarządzanie pamięcią
- Tworzenie puli pamięci
- Niestandardowy alokator pamięci
- Stosowanie polimorficznych alokatorów pamięci
- Implementowanie niestandardowego zasobu pamięciowego
- Podsumowanie
Rozdział 8. Programowanie z przetwarzaniem w czasie kompilacji
- Wprowadzenie do metaprogramowania z użyciem szablonów
- Tworzenie szablonów
- Stosowanie liczb całkowitych jako parametrów szablonu
- Tworzenie specjalizacji szablonu
- Jak kompilator przetwarza funkcję szablonową?
- Skrócone szablony funkcji
- Pobieranie typu zmiennej za pomocą specyfikatora decltype
- Cechy typów
- Kategorie cech typów
- Stosowanie cech typów
- Programowanie z użyciem stałych wyrażeń
- Działanie funkcji ze słowem kluczowym constexpr w czasie wykonywania programu
- Deklarowanie funkcji natychmiastowych za pomocą słowa kluczowego consteval
- Instrukcja if constexpr
- Sprawdzanie błędów programistycznych w czasie kompilacji
- Ograniczenia i koncepty
- Szablon Point2D bez ograniczeń
- Omówienie składni ograniczeń i konceptów
- Wersja szablonu Point2D z ograniczeniami
- Dodawanie ograniczeń do kodu
- Koncepty w bibliotece standardowej
- Praktyczne przykłady metaprogramowania
- Przykład nr 1: tworzenie generycznej bezpiecznej funkcji rzutowania
- Przykład nr 2: obliczanie skrótów łańcuchów znaków w czasie kompilacji
- Podsumowanie
Rozdział 9. Podstawowe narzędzia
- Reprezentowanie wartości opcjonalnych za pomocą typu std::optional
- Opcjonalne zwracane wartości
- Opcjonalne zmienne składowe
- Unikanie pustych stanów w wyliczeniach
- Sortowanie i porównywanie wartości typu std::optional
- Kolekcje niejednorodne o stałej wielkości
- Stosowanie typu std::pair
- Typ std::tuple
- Kolekcje niejednorodne o dynamicznie zmienianej wielkości
- Typ std::variant
- Kolekcje niejednorodne z obiektami typu std::variant
- Dostęp do wartości z kontenera elementów typu VariantType
- Praktyczne przykłady
- Przykład nr 1: projekcje i operatory porównania
- Przykład nr 2: refleksja
- Podsumowanie
Rozdział 10. Obiekty pośredniczące i leniwe przetwarzanie
- Wprowadzenie do leniwego przetwarzania i obiektów pośredniczących
- Przetwarzanie leniwe i przetwarzanie zachłanne
- Obiekty pośredniczące
- Stosowanie obiektów pośredniczących do zapobiegania tworzeniu obiektów
- Porównywanie scalanych łańcuchów znaków z wykorzystaniem obiektu pośredniczącego
- Implementowanie obiektu pośredniczącego
- Modyfikator r-wartości
- Przypisywanie połączonej wartości do obiektu pośredniczącego
- Ocena wydajności
- Odraczanie obliczania kwadratów
- Prosta klasa reprezentująca wektory dwuwymiarowe
- Obliczenia matematyczne
- Implementowanie klasy LengthProxy
- Porównywanie długości za pomocą klasy LengthProxy
- Obliczanie długości za pomocą klasy LengthProxy
- Ocena wydajności
- Pomysłowe przeciążanie operatorów i obiekty pośredniczące
- Operator potoku jako metoda rozszerzająca
- Podsumowanie
Rozdział 11. Współbieżność
- Podstawy współbieżności
- Co sprawia, że programowanie współbieżne jest trudne?
- Współbieżność a równoległość
- Porcjowanie czasu
- Współdzielona pamięć
- Sytuacja wyścigu
- Muteks
- Zakleszczenie
- Zadania synchroniczne i zadania asynchroniczne
- Programowanie współbieżne w języku C++
- Biblioteka obsługi wątków
- Dodatkowe podstawowe mechanizmy synchronizacji w standardzie C++20
- Obsługa zmiennych atomowych w języku C++
- Model dostępu do pamięci w języku C++
- Programowanie bez blokad
- Przykład: kolejka bez blokad
- Wskazówki dotyczące wydajności
- Zapobieganie rywalizacji
- Unikanie operacji blokujących
- Liczba wątków i rdzeni procesora
- Priorytety wątków
- Koligacja wątków
- Niezamierzone współdzielenie
- Podsumowanie
Rozdział 12. Korutyny i leniwe generatory
- Kilka przykładów uzasadniających stosowanie korutyn
- Abstrakcja reprezentująca korutyny
- Podprocedury i korutyny
- Wykonywanie podprocedur i korutyn w procesorze
- Korutyny bezstosowe i korutyny stosowe
- Czego Czytelnik nauczył się do tego miejsca?
- Korutyny w języku C++
- Co zostało uwzględnione w standardzie języka C++ (i co zostało pominięte)?
- Co sprawia, że funkcja w języku C++ jest korutyną?
- Minimalny, lecz kompletny przykład
- Alokowanie stanu korutyny
- Zapobieganie wiszącym referencjom
- Obsługa błędów
- Punkty konfiguracyjne
- Generatory
- Implementowanie generatora
- Stosowanie klasy Generator
- Praktyczny przykład zastosowania generatorów
- Wydajność
- Podsumowanie
Rozdział 13. Programowanie asynchroniczne z użyciem korutyn
- Jeszcze o typach awaitable
- Automatyczne punkty wstrzymywania
- Implementowanie prostego typu reprezentującego zadanie
- Obsługa zwracanych wartości i wyjątków
- Wznawianie oczekującej korutyny
- Dodawanie obsługi zadań zwracających void
- Synchroniczne oczekiwanie na ukończenie zadania
- Testowanie asynchronicznych zadań z użyciem funkcji sync_wait()
- Tworzenie nakładki na API opartym na wywołaniach zwrotnych
- Współbieżny serwer zbudowany za pomocą biblioteki Boost.Asio
- Implementowanie serwera
- Uruchamianie serwera i nawiązywanie z nim połączenia
- Co osiągnęliśmy za pomocą serwera (i czego wciąż brakuje)?
- Podsumowanie
Rozdział 14. Algorytmy równoległe
- Znaczenie równoległości
- Algorytmy równoległe
- Ocena algorytmów równoległych
- Jeszcze o prawie Amdahla
- Implementowanie równoległego algorytmu std::transform()
- Implementowanie równoległej wersji algorytmu std::count_if()
- Implementowanie równoległej wersji algorytmu std::copy_if()
- Algorytmy równoległe z biblioteki standardowej
- Strategie wykonywania
- Obsługa wyjątków
- Dodatki i zmiany w algorytmach równoległych
- Zrównoleglanie pętli for opartej na indeksie
- Wykonywanie algorytmów w procesorze graficznym
- Podsumowanie
Kategoria: | Programowanie |
Zabezpieczenie: |
Watermark
|
ISBN: | 978-83-283-9709-5 |
Rozmiar pliku: | 5,5 MB |