고성능을 위한 언어 C++ [이론과 C++17, 메모리 관리, 동시성, STL 알고리즘 모범 사례]
- 원서명C++ High Performance: Boost and optimize the performance of your C++17 code (ISBN 9781787120952)
- 지은이빅터 세르(Viktor Sehr), 비요른 앤드리스트(Björn Andrist)
- 옮긴이최준
- ISBN : 9791161753911
- 35,000원
- 2020년 01월 31일 펴냄
- 페이퍼백 | 456쪽 | 188*235mm
- 시리즈 : 프로그래밍 언어
책 소개
요약
누구나 C++를 익히고 나면, 원하는 프로그램을 어떻게 만들지 고민하게 된다. 하지만 프로그래머라면 만들고자 하는 기능이 무엇이든지 간에 이 책에서 제시하는 더 빠르고 가벼운 프로그램 설계 방법을 항상 고려하는 것이 좋다. 성능의 여러 측면을 C++ 언어로 설명한 이론과 예제는 더 좋은 프로그램을 제작하는 데 유용한 배경지식이 될 것이다.
추천의 글
C++는 1983년에 등장한 이후로 한 해도 멈추지 않고 발전을 거듭했다. C 언어를 바탕으로 단일 프론트엔드 언어에서 컴파일러 세계의 일등 시민으로 자리 잡고 있다. 매번 새로운 C++의 표준은 가끔 지나칠 정도로 많은 기능이 추가된다. 스트롭스트룹(Stroustrup)은 C++ 안에서 훨씬 더 작고 깔끔한 언어가 태어나려 한다고 말하기도 했다.
문제는 우리가 찾는 더 작고 깔끔한 언어가 상황에 따라 변하고 있다는 점이다. C++를 마스터하는 것은 이제 여러 특정 분야에 맞게 발전한 영역의 언어를 익히는 것과 마찬가지다. 임베디드(embedded) 시스템에 잘 맞는 일종의 변형 언어는 대규모의 기업용 애플리케이션에서는 통하지 않고, 강력한 게임 엔진용 표현은 문서 처리기에서는 통하지 않는다.
이 책은 고성능용 코드를 신속하게 개발하는 하나의 C++ 변형을 설명한다. C++11로 시작해서 방대한 기능을 가진 C++ 언어와 애플리케이션의 작성에 더 많은 시간을 소비하지만, 세부 기능의 실행에는 시간을 덜 소비하는 C++ STL을 아우른다. 이것이 이 책이 C++를 바라보는 관점이다.
이 책의 개별 주제는 애플리케이션 개발과 컴퓨터 공학을 큰 틀에서 다룬다. 최신 C++ 기술의 정보를 따라잡고자 하는 독자에게 필요한 핵심적인 변화를 다뤄서 중심을 잡아준다. 여기서 나오는 특정 예제와 논리적 전개 등은 알고리즘의 기본적인 사용법에서 출발해 GPU에서 OpenCL로 자신의 알고리즘을 실행할 수 있도록 실력을 향상시켜준다. 현재 C++의 근본적인 문제(메모리 관리와 소유, 시간과 공간에 대한 고민, 고급 템플릿 사용법 등)를 단계적으로 풀어가면 이 책의 후반부에서는 자신감을 갖고 고급 기술의 영역에 도달하게 될 것이다.
나는 크거나 작은 로우레벨, 관리되는 프로젝트, 심지어 맞춤 설계된 언어를 사용하는 프로젝트 등 다양한 프로젝트를 수행했지만, C++는 항상 내 마음속에 특별하게 간직하고 있다. 2000년대에 내가 첫 정규직으로 근무한 게임 기술 회사에서의 주 업무는 C++ 코드를 작성하는 것이었다. 업무의 주요 기술이 편집기와 스크립팅 언어에 C++ 코드 베이스를 반영하는 것이었으므로 그 일을 사랑했다.
어떤 사람은 C++가 강아지에 다리를 덧붙여 문어로 만든 것 같다고 얘기한다. 나는 C++가 의도하지 않은 방향으로 가지 않도록 코드 베이스를 망치로 두들겨 가면서 많은 노력을 기울였다. 아직까지는 그 문어가 나름의 방식대로 아름답고 효과적이다.
C++는 과거에서 현재까지 엄청난 발전을 해왔다. 이제 가능성으로 가득한 흥미진진한 세상으로 가는 문을 독자에게 열어주는 게 된 것은 나의 영광이다. 빅터(Viktor)와 비요른(Björn)은 경험이 많고 뛰어난 업적을 남긴 멋진 개발자이며, 독자를 위해 매우 많고 훌륭한 것을 저장해두고 있다.
- 벤 가니(Ben Garney)
/엔진 컴퍼니(The Engine Company)의 CEO
이 책에서 다루는 내용
■ 자신이 만든 코드를 향상시킬 수 있는 흥미로운 도구 사용법
■ 코드를 최적화하기 위한 성능 병목지점을 찾아내는 방법
■ GPU 연산을 활용하는 애플리케이션 개발
■ 동시 프로그래밍의 장점 활용
■ 예외 처리를 통해 애플리케이션 오류에서 보호하는 코드 제작
■ STL 컨테이너와 알고리즘의 효율적인 활용
■ 부스트 컨테이너 확장 도구
■ 사용자 정의 메모리 할당자를 사용한 효율적인 메모리 관리
이 책의 대상 독자
독자가 C++와 컴퓨터 구조의 기초 지식과 자신의 기술을 향상시키는 데 타고난 흥미를 갖고 있다고 기대한다. 바라건대 이 책을 마치고 나면 성능, 구조 측면에서 자신의 C++ 애플리케이션을 향상시킬 수 있는 몇 가지 방법을 얻을 수 있을 것이다. “아, 그렇구나!”’라고 생각하는 순간을 갖기 바란다.
이 책의 구성
1장, ‘C++의 간단한 소개’에서는 무비용 추상화, 값 의미 체계, 상수 수정, 명시적 소유, 오류 처리 등과 같은 일부 중요한 특징을 소개한다. C++의 단점도 알아본다.
2장, ‘최신 C++ 개념’에서는 auto를 사용한 자동 타입 추정과 람다 함수, 이동 의미 체계, std::optional, std::any 등을 개괄적으로 다룬다.
3장, ‘성능 측정’에서는 점근적 복합성, 빅 O 표시법, 실용적 성능 테스트와 코드를 프로파일해 문제 지점을 찾는 방법을 설명한다.
4장, ‘데이터 구조’에서는 데이터에 빠르게 접근할 수 있도록 구성하는 작업의 중요성을 보여준다. std::vector, std::list, std::unorderedmap, std::priorityqueue와 같은 STL 컨테이너를 소개하고, 마지막으로 평행 배열의 반복 연산 방법을 알아본다.
5장, ‘반복자’에서는 반복 연산자의 개념을 깊이 있게 살펴보고, 반복 연산자가 단순히 컨테이너에 객체를 참조하는 것을 뛰어 넘는 방법을 보여준다.
6장, ‘STL 알고리즘’에서는 STL 알고리즘의 명백한 장점과 아주 명백하지는 않은 장점을 설명한다. 또한 STL 알고리즘의 한계와 새로운 Ranges 라이브러리로 이러한 한계를 극복하는 방법을 살펴본다.
7장, ‘메모리 관리’에서는 안전하고 효율적인 메모리 관리법을 집중적으로 다룬다. 메모리 소유권, RAII, 스마트 포인터, 스택 메모리, 동적 메모리, 사용자 메모리 할당 등을 다룬다.
8장, ‘메타프로그래밍과 컴파일 시 평가’에서는 constexpr, 다원화 컨테이너, typetraits, std::enableif, std::is_detected와 같은 메타프로그래밍 개념을 알아본다. 또한 리플렉션과 같은 실용적인 메타프로그래밍 활용 사례도 제공한다.
9장, ‘프록시 객체와 지연 평가’에서는 프록시 객체가 깔끔한 구문을 유지하면서 아래로는 최적화를 수행하는 데 쓰이는 프록시 객체를 알아본다. 더불어 연산자 오버로딩의 창의적인 활용도 일부 알아본다.
10장, ‘동시성’에서는 병렬 실행과 공유 메모리, 데이터 경합, 교착 상태 등 동시 처리 프로그래밍의 기본을 다룬다. 또한 C++의 스레드 지원 라이브러리, 아토믹 라이브러리, C++ 메모리 모델도 소개한다.
11장, ‘병렬 STL’에서는 병렬 알고리즘 작성의 복합성을 보여준다. STL과 부스트 연산용 병렬 확장 기능을 사용하는 병렬 처리 STL 알고리즘을 활용하는 방법을 알아본다.
목차
목차
- 1장. C++의 간단한 소개
- C++의 사용 이유
- 비용이 들지 않는 추상화
- 이식성
- 견고성
- C++의 현재
- 이 책의 목표
- 독자에게 기대하는 지식
- 다른 언어와 C++의 비교
- 언어의 성능 경쟁
- 성능과 관련 없는 C++ 언어의 기능
- 객체 소유와 C++의 가비지 컬렉션
- C++ 참조를 사용한 널 객체 예방
- C++의 단점
- 클래스 인터페이스와 예외 처리
- 엄격한 클래스 인터페이스
- 오류 처리와 자원 관리
- 이 책에서 사용한 라이브러리
- 요약
- C++의 사용 이유
- 2장. 최신 C++ 개념
- auto 키워드를 사용한 자동 타입 추론
- 함수 서명에서 auto 사용
- 변수에서 auto 사용
- 람다 함수
- C++ 람다 함수의 기본 구문
- 캡처 블록
- 람다와 std::function
- 다형성 람다
- 포인터에 대한 상수 전파
- 이동 의미론 설명
- 복사 생성, 교환, 이동
- 자원의 획득과 3의 법칙
- 이동 의미론 소개
- 명명된 변수와 오른쪽 값
- 기본 이동 의미론과 영의 법칙
- std::optional로 옵션 값 표현
- 옵션 반환값
- 옵션 멤버 변수
- 정렬과 std::optional의 비교
- 동적인 값을 std::any로 표현
- std::any의 성능
- 요약
- auto 키워드를 사용한 자동 타입 추론
- 3장. 성능 측정
- 점근적 복잡도와 빅 O 표기법
- 증가율
- 분할 상환 시간 복잡도
- 측정 대상
- 성능의 속성
- 성능 테스트: 모범 사례
- 코드의 이해와 핵심 지점
- 프로파일러
- 요약
- 점근적 복잡도와 빅 O 표기법
- 4장. 데이터 구조
- 컴퓨터 메모리의 속성
- STL 컨테이너
- 시퀀스 컨테이너
- 연관 컨테이너
- 정렬된 집합과 맵
- 비정렬 집합과 맵
- 컨테이너 어댑터
- 평행 배열
- 요약
- 5장. 반복자
- 반복자 개념
- 반복자 분류
- 포인터와 유사한 문법
- 생성기로서의 반복자
- 반복자 특성
- 실용적인 예제: 범위 내의 부동소수점 포인트 값 반복 연산
- 요약
- 반복자 개념
- 6장. STL 알고리즘
- 블록 구성을 위한 STL 알고리즘
- STL 알고리즘의 개념
- STL 알고리즘과 직접 만든 for 반복문의 비교
- STL과 범위 라이브러리의 미래
- STL 반복자의 제약 사항
- 범위 라이브러리 소개
- 액션, 뷰, 알고리즘
- 요약
- 블록 구성을 위한 STL 알고리즘
- 7장. 메모리 관리
- 컴퓨터 메모리
- 가상 주소 공간
- 메모리 페이지
- 스레싱
- 프로세스 메모리
- 스택 메모리
- 힙 메모리
- 메모리의 객체
- 객체의 생성과 해제
- 메모리 배치
- 패딩
- 메모리 소유권
- 암시적 자원 관리
- 컨테이너
- 스마트 포인터
- 작은 크기를 사용한 최적화
- 사용자 정의 메모리 관리
- 아레나 만들기
- 사용자 정의 메모리 할당자
- 요약
- 컴퓨터 메모리
- 8장. 메타프로그래밍과 컴파일 시 평가
- 템플릿 메타프로그래밍 소개
- 템플릿 파라미터로 정수 사용
- 컴파일러가 템플릿 함수를 처리하는 방법
- 컴파일 시에 오류를 트리거하는 static_assert 사용
- 타입 특성
- 타입 특성 분류
- 타입 특성 사용
- decltype을 사용한 변수 타입 가져오기
- std::enableift를 사용해 타입에 따른 조건적 함수 활성화
- std::is_detected로 클래스 멤버 들여다보기
- constexpr 키워드
- 런타임 구문의 constexpr 함수
- std::integral_constant를 사용한 컴파일 시 처리 과정의 검증
- if constexpr 구문
- 다원화 컨테이너
- 정적인 크기의 다원화 컨테이너
- 동적 크기의 혼합 컨테이너
- std::variant
- variant에 접근
- variant의 다원화 컨테이너
- variant 컨테이너의 값에 접근
- std::get 전역 함수
- 메타프로그래밍 실전 예제
- 사례 1: 리플렉션
- 전역 함수의 조건적 오버로딩
- 사례 2: 안전한 포괄적 형 변환 함수 작성
- 사례 3: 컴파일 시의 해시 문자열
- 요약
- 템플릿 메타프로그래밍 소개
- 9장. 프록시 객체와 지연 평가
- 지연 평가와 프록시 객체의 소개
- 지연 평가와 선행 평가의 비교
- 프록시 객체
- 프록시를 사용한 문자열 합치기 비교
- 프록시 구현
- r-value 수정자
- 합쳐진 프록시 할당
- 거리 비교 시 제곱 계산의 보류
- 간단한 2차원 지점 클래스
- 수학적 배경
- DistProxy 객체 구현
- 더 유용하도록 DistProxy 확장
- DistProxy를 사용한 거리 비교
- DistProxy로 거리 계산
- 성능 평가
- 연산자 오버로딩과 프록시 객체 생성
- 확장 메서드로서의 파이프 연산자
- 중위 연산자
- 더 읽을거리
- 요약
- 지연 평가와 프록시 객체의 소개
- 10장. 동시성
- 동시성의 기본
- 동시 프로그래밍이 어려운 이유
- 동시성과 병렬성
- 시분할
- 공유 메모리
- 데이터 경합
- 뮤텍스
- 교착 상태
- 동기 작업과 비동기 작업
- C++ 동시 프로그래밍
- 스레드 지원 라이브러리
- C++의 아토믹 지원
- C++ 메모리 모델
- 잠금 없는 프로그래밍
- 잠금 없는 큐의 예
- 성능 가이드
- 경합 방지
- 대기 동작 방지
- 스레드와 CPU 코어의 개수
- 스레드 우선순위
- 스레드 선호
- 거짓 공유
- 요약
- 11장. 병렬 STL
- 병렬 처리의 중요성
- 병렬 알고리즘
- 병렬 std::transform() 구현
- 병렬 std::count_if 구현
- 병렬 std::copy_if 구현
- 병렬 STL
- 실행 정책
- 병렬 버전으로 알고리즘 수정
- 인덱스 기반의 for 반복문 병렬화
- GPU에서 STL 알고리즘 실행
- GPU API와 병렬 작업
- STL 알고리즘과 GPU
- 부스트 컴퓨트
- 부스트 컴퓨트 기본 개념
- OpenCL
- 부스트 컴퓨트 초기화
- 부스트 컴퓨트에 간단한 transform-reduce 알고리즘 전달
- 부스트 컴퓨트에서 조건자 사용
- 부스터 컴퓨트에서 사용자 정의 커널 사용
- 요약