C++ High Performance - Björn Andrist - E-Book

C++ High Performance E-Book

Björn Andrist

0,0
35,99 €

-100%
Sammeln Sie Punkte in unserem Gutscheinprogramm und kaufen Sie E-Books und Hörbücher mit bis zu 100% Rabatt.

Mehr erfahren.
Beschreibung

Write code that scales across CPU registers, multi-core, and machine clusters

Key Features

  • Explore concurrent programming in C++
  • Identify memory management problems
  • Use SIMD and STL containers for performance improvement

Book Description

C++ is a highly portable language and can be used to write both large-scale applications and performance-critical code. It has evolved over the last few years to become a modern and expressive language. This book will guide you through optimizing the performance of your C++ apps by allowing them to run faster and consume fewer resources on the device they're running on without compromising the readability of your code base.

The book begins by helping you measure and identify bottlenecks in a C++ code base. It then moves on by teaching you how to use modern C++ constructs and techniques. You'll see how this affects the way you write code. Next, you'll see the importance of data structure optimization and memory management, and how it can be used efficiently with respect to CPU caches. After that, you'll see how STL algorithm and composable Range V3 should be used to both achieve faster execution and more readable code, followed by how to use STL containers and how to write your own specialized iterators.

Moving on, you’ll get hands-on experience in making use of modern C++ metaprogramming and reflection to reduce boilerplate code as well as in working with proxy objects to perform optimizations under the hood. After that, you’ll learn concurrent programming and understand lock-free data structures. The book ends with an overview of parallel algorithms using STL execution policies, Boost Compute, and OpenCL to utilize both the CPU and the GPU.

What you will learn

  • Benefits of modern C++ constructs and techniques
  • Identify hardware bottlenecks, such as CPU cache misses, to boost performance
  • Write specialized data structures for performance-critical code
  • Use modern metaprogramming techniques to reduce runtime calculations
  • Achieve efficient memory management using custom memory allocators
  • Reduce boilerplate code using reflection techniques
  • Reap the benefits of lock-free concurrent programming
  • Perform under-the-hood optimizations with preserved readability using proxy objects
  • Gain insights into subtle optimizations used by STL algorithms
  • Utilize the Range V3 library for expressive C++ code
  • Parallelize your code over CPU and GPU, without compromising readability

Who this book is for

If you're a C++ developer looking to improve the speed of your code or simply wanting to take your skills up to the next level, then this book is perfect for you.

Viktor Sehr is the main developer at Toppluva, working with a highly-optimized graphics engine aimed for mobile hardware. He has 10 years of professional experience using C++, with real-time graphics, audio, and architectural design as his focus areas. Through his career, he has developed medical visualization software at Mentice and Raysearch Laboratories as well as real-time audio applications at Propellerhead Software. Viktor holds an M.S. in media science from Linköping University. Björn Andrist is a freelance software consultant currently focusing on audio applications. For more than 10 years, he has been working professionally with C++ in projects ranging from Unix server applications to real-time audio applications on desktop and mobile. In the past, he has also taught courses in algorithms and data structures, concurrent programming, and programming methodologies. Björn holds a BS in computer engineering and an MS in computer science from KTH Royal Institute of Technology.

Sie lesen das E-Book in den Legimi-Apps auf:

Android
iOS
von Legimi
zertifizierten E-Readern

Seitenzahl: 449

Veröffentlichungsjahr: 2018

Bewertungen
0,0
0
0
0
0
0
Mehr Informationen
Mehr Informationen
Legimi prüft nicht, ob Rezensionen von Nutzern stammen, die den betreffenden Titel tatsächlich gekauft oder gelesen/gehört haben. Wir entfernen aber gefälschte Rezensionen.



C++ High Performance

 

 

 

 

 

 

Boost and optimize the performance of your C++17 code

 

 

 

 

 

 

 

 

 

 

 

Viktor Sehr
Björn Andrist

 

 

 

 

 

 

 

 

 

 

 

 

BIRMINGHAM - MUMBAI

C++ High Performance

Copyright © 2018 Packt Publishing

All rights reserved. No part of this book may be reproduced, stored in a retrieval system, or transmitted in any form or by any means, without the prior written permission of the publisher, except in the case of brief quotations embedded in critical articles or reviews.

Every effort has been made in the preparation of this book to ensure the accuracy of the information presented. However, the information contained in this book is sold without warranty, either express or implied. Neither the author(s), nor Packt Publishing or its dealers and distributors, will be held liable for any damages caused or alleged to have been caused directly or indirectly by this book.

Packt Publishing has endeavored to provide trademark information about all of the companies and products mentioned in this book by the appropriate use of capitals. However, Packt Publishing cannot guarantee the accuracy of this information.

Commissioning Editors: Aaron LazarAcquisition Editor: Denim PintoContent Development Editors: Nikhil BorkarTechnical Editor: Jijo MaliyekalCopy Editor: Safis EditingProject Coordinator: Vaidehi SawantProofreader: Safis EditingIndexers: Rekha NairGraphics: Tania DuttaProduction Coordinator: Arvindkumar Gupta

First published: January 2018

Production reference: 1300118

Published by Packt Publishing Ltd. Livery Place 35 Livery Street Birmingham B3 2PB, UK.

ISBN 978-1-78712-095-2

www.packtpub.com

mapt.io

Mapt is an online digital library that gives you full access to over 5,000 books and videos, as well as industry leading tools to help you plan your personal development and advance your career. For more information, please visit our website.

Why subscribe?

Spend less time learning and more time coding with practical eBooks and Videos from over 4,000 industry professionals

Improve your learning with Skill Plans built especially for you

Get a free eBook or video every month

Mapt is fully searchable

Copy and paste, print, and bookmark content

PacktPub.com

Did you know that Packt offers eBook versions of every book published, with PDF and ePub files available? You can upgrade to the eBook version at www.PacktPub.com and as a print book customer, you are entitled to a discount on the eBook copy. Get in touch with us at [email protected] for more details.

At www.PacktPub.com, you can also read a collection of free technical articles, sign up for a range of free newsletters, and receive exclusive discounts and offers on Packt books and eBooks.

Foreword

C++ stepped onto the stage in 1983 and hasn’t stopped reinventing itself for a single year since. It has gone from a single frontend language on top of C to a first-class citizen of the compiler world. Each new C++ standard has added substantial functionality, sometimes to excess. In the words of Stroustrup, “Within C++, there is a much smaller and cleaner language struggling to get out.”

The problem, of course, is that the “smaller and cleaner language” to be found within C++ changes with situation. Mastering C++ is akin to mastering a multitude of domain-specific languages, each tailored to a specific use. The dialect that makes sense for embedded system is nonsensical for large enterprise applications, and the phrasing that powers a game engine is unbearable when applied to a word processor.

C++ High Performance teaches you a C++ dialect for rapidly developing high-performance code. From C++11 onward, there have been a vast array of features in both the C++ language and the C++ STL that let you spend more time writing your application and less time handling implementation details. This is the focus of the book and where it shines.

Each topic is framed in the larger context of application development and computer science. For the reader who needs to get up to speed with the latest C++ techniques on a short notice, this information provides the necessary landmarks to stay oriented. Specific examples, recipes, and logical progressions take you from a basic use of auto and <algorithm> all the way up to using Boost to transparently run your algorithms on the GPU via OpenCL. Fundamental issues around modern C++ (memory management and ownership, considerations of time and space, advance template usage, and others) are explained step by step so that, by the later chapters, the readers proceed into advanced territory with confidence.

I have worked on a wide variety of projects—large and small, low level and managed, and some even in custom languages I designed and built—but C++ holds a special place in my heart. My first full-time job was writing C++ code for a game technology company in the early 2000s. I loved it, not least of all because a big part of the technology revolved around the reflection of the C++ code base into the editor and scripting language. Someone once described C++ as an octopus made by nailing extra legs onto a dog, and I spent a lot of time with a hammer making our code base do things that C++ was never intended to do. Yet, the octopus we ended up with was, in its own way, beautiful and very effective.

C++ has evolved tremendously since those days, and it is my privilege to open the door for you as you walk into an exciting new world of possibilities. Viktor and Björn are brilliant and experienced developers with a remarkable pedigree, and they have a lot of great things in store for you.

Ben Garney CEO, The Engine Company

Contributors

About the authors

Viktor Sehr is the main developer at Toppluva, working with a highly-optimized graphics engine aimed for mobile hardware.He has 10 years of professional experience using C++, with real-time graphics, audio, and architectural design as his focus areas. Through his career, he has developed medical visualization software at Mentice and Raysearch Laboratories as well as real-time audio applications at Propellerhead Software. Viktor holds an M.S. in media science from Linköping University.

I would like to acknowledge the colleagues who have broadened my knowledge in programming during my carrier (in alphabetical order); Andreas Brinck, Peter Forsberg, Rickard Holmberg, Sigfred Håvardssen, Tobias Kruseborn, Philippe Peirano, Johan Riddersporre, Marcus Sonestedt, and Mattias Unger. Additionally, I would like to thank our technical reviewers Louis E. Mauget, and especially, Sergey Gomon. Lastly, my Hanna, for your love and support.

Björn Andrist is a freelance software consultant currently focusing on audio applications. For more than 10 years, he has been working professionally with C++ in projects ranging from Unix server applications to real-time audio applications on desktop and mobile. In the past, he has also taught courses in algorithms and data structures, concurrent programming, and programming methodologies. Björn holds a BS in computer engineering and an MS in computer science from KTH Royal Institute of Technology.

First I would like to thank the team at Packt Publishing who helped and contributed to make this book possible. Thank you Louis E. Mauget for reviewing the book and providing me with insights, knowledge, and encouragement. A special thanks goes to Sergey Gomon, who has done an outstanding job reviewing the book and working with the code examples. Last, and most of all, I must thank my family for their support and for understanding my many hours at the computer - thank you Aleida, Agnes, and Clarence.

About the reviewers

Sergey Gomon started his journey in IT 10 years ago in Belarus State University of Informatics and Radioelectronics in the artificial intelligence department. He has about 8 years of industrial programming experience using C++ in several fields, such as network programming, information security, and image processing. In his free time, he likes reading, traveling, and studying something new.

He currently works at Regula and SolarWinds MSP, and is an activist of the CoreHard C++ community.

I want to say thanks to my friend Artem Lapitsky who is always ready to share his wisdom with me.

 

Louis E. Mauget never saw the ENIAC but coded in those languages, adding several modern languages and frameworks. C++ continues to evolve, and Lou evolves with it. Interested in reactive functional programming, containers, and deep learning, he blogs about software technology for Keyhole Software, where he works as a senior software engineer. A coauthor of three computer books, he also wrote IBM developerWorks tutorials and a WebSphere Journal two-part LDAP tutorial. He cowrote several J2EE certification tests for IBM and has been a reviewer for Packt Publishing and others.

 

 

 

Packt is searching for authors like you

If you're interested in becoming an author for Packt, please visit authors.packtpub.com and apply today. We have worked with thousands of developers and tech professionals, just like you, to help them share their insight with the global tech community. You can make a general application, apply for a specific hot topic that we are recruiting an author for, or submit your own idea.

Table of Contents

Preface

Who this book is for

What this book covers

To get the most out of this book

Download the example code files

Conventions used

Get in touch

Reviews

A Brief Introduction to C++

Why C++?

Zero-cost abstractions

Programming languages and machine code abstractions

Abstractions in other languages

Portability

Robustness

C++ of today

The aim of this book

Expected knowledge of the reader

C++ compared with other languages

Competing languages and performance

Non-performance-related C++ language features

Value semantics

Const correctness

Object ownership and garbage collection in C++

Avoiding null objects using C++ references

Drawbacks of C++

Class interfaces and exceptions

Strict class interfaces

Error handling and resource acquisition

Preserving the valid state

Resource acquisition

Exceptions versus error codes

Libraries used in this book

Summary

Modern C++ Concepts

Automatic type deduction with the auto keyword 

Using auto in function signatures

Using auto for variables

Const reference

Mutable reference

Forwarding reference

Conclusion

The lambda function

Basic syntax of a C++ lambda function

The capture block

Capture by reference versus capture by value

Similarities between a Lambda and a class

Initializing variables in capture

Mutating lambda member variables

Mutating member variables from the compiler's perspective

Capture all

Assigning C function pointers to lambdas

Lambdas and std::function

Assigning lambdas to std::functions

Implementing a simple Button class with std::function

Performance consideration of std::function

An std::function cannot be inlined

An std::function heap allocates and captures variables

Invoking an std::function requires a few more operations than a lambda

The polymorphic lambda

Creating reusable polymorphic lambdas

Const propagation for pointers

Move semantics explained

Copy-construction, swap, and move

Copy-constructing an object

Swapping two objects

Move-constructing an object

Resource acquisition and the rule of three

Implementing the rule of three

Constructor

Limitations of the rule of three

Avoiding copies without move semantics

Introducing move semantics

Named variables and r-values

Accept arguments by move when applicable

Default move semantics and the rule of zero

Rule of zero in a real code base

A note on empty destructors

A common pitfall - moving non-resources

Applying the && modifier to class member functions

Representing optional values with std::optional

Optional return values

Optional member variables

Sorting and comparing std::optional

Representing dynamic values with std::any

Performance of std::any

Summary

Measuring Performance

Asymptotic complexity and big O notation

Growth rates

Amortized time complexity

What to measure?

Performance properties

Performance testing – best practices

Knowing your code and hot spots

Profilers

Instrumentation profilers

Sampling profilers

Summary

Data Structures

Properties of computer memory

STL containers

Sequence containers

Vector and array

Deque

List and forward_list

The basic_string

Associative containers

Ordered sets and maps

Unordered sets and maps

Hash and equals

Hash policy

Container adaptors

Priority queues

Parallel arrays

Summary

A Deeper Look at Iterators

The iterator concept

Iterator categories

Pointer-mimicking syntax

Iterators as generators

Iterator traits

Implementing a function using iterator categories

Extending the IntIterator to bidirectional

Practical example – iterating floating point values within a range

Illustrated usage examples

Utility functions

How to construct a linear range iterator

Iterator usage example

Generalizing the iterator pair to a range

The make_linear_range convenience function

Linear range usage examples

Summary

STL Algorithms and Beyond

Using STL algorithms as building blocks

STL algorithm concepts

Algorithms operate on iterators

Implementing a generic algorithm that can be used with any container

Iterators for a range point to the first element and the element after the last

Algorithms do not change the size of the container

Algorithms with output require allocated data

Algorithms use operator== and operator< by default

Custom comparator function

General-purpose predicates

Algorithms require move operators not to throw

Algorithms have complexity guarantees

Algorithms perform just as well as C library function equivalents

STL algorithms versus handcrafted for-loops

Readability and future-proofing

Real-world code base example

Usage examples of STL algorithms versus handcrafted for-loops

Example 1 – Unfortunate exceptions and performance problems

Example 2 – STL has subtle optimizations even in simple algorithms

Sorting only for the data you need to retrieve

Use cases

Performance evaluation

The future of STL and the ranges library

Limitations of the iterators in STL

Introduction to the ranges library

Composability and pipeability

Actions, views, and algorithms

Actions

Views

Algorithms

Summary

Memory Management

Computer memory

The virtual address space

Memory pages

Thrashing

Process memory

Stack memory

Heap memory

Objects in memory

Creating and deleting objects

Placement new

The new and delete operators

Memory alignment

Padding

Memory ownership

Handling resources implicitly

Containers

Smart pointers

Unique pointer

Shared pointer

Weak pointer

Small size optimization

Custom memory management

Building an arena

A custom memory allocator

Summary

Metaprogramming and Compile-Time Evaluation

Introduction to template metaprogramming

Using integers as template parameters

How the compiler handles a template function

Using static_assert to trigger errors at compile time

Type traits

Type trait categories

Using type traits

Receiving the type of a variable with decltype

Conditionally enable functions based on types with std::enable_if_t

Introspecting class members with std::is_detected

Usage example of is_detected and enable_if_t combined

The constexpr keyword

Constexpr functions in a runtime context

Verify compile-time computation using std::integral_constant

The if constexpr statement

Comparison with runtime polymorphism

Example of generic modulus function using if constexpr

Heterogeneous containers

Static-sized heterogenous containers

The std::tuple container

Accessing the members of a tuple

Iterating std::tuple

Unrolling the tuple

Implementing other algorithms for tuples

Accessing tuple elements

Structured bindings

The variadic template parameter pack

An example of a function with variadic number of arguments

How to construct a variadic parameter pack

Dynamic-sized heterogenous containers

Using std::any as the base for a dynamic-size heterogenous container

The std::variant

Visiting variants

Heterogenous container of variants

Accessing the values in our variant container

Global function std::get

Real world examples of metaprogramming

Example 1 – Reflection

Making a class reflect its members

C++ libraries which simplifies reflection

Using the reflection

Evaluating the assembler output of the reflection

Conditionally overloading global functions

Testing reflection capabilities

Example 2 – Creating a generic safe cast function

Example 3 – Hash strings at compile time

The advantages of compile-time hash sum calculation

Implement and verify a compile-time hash function

Constructing a PrehashedString class

Forcing PrehashedString to only accept compile time string literals

Evaluating PrehashedString

Evaluating get_bitmap_resource() with PrehashedString

Summary

Proxy Objects and Lazy Evaluation

An introduction to lazy evaluation and proxy objects

Lazy versus eager evaluation

Proxy objects

Comparing concatenated strings using a proxy

Implementing the proxy

Performance evaluation

The r-value modifier

Assigning a concatenated proxy

Postponing an sqrt computation when comparing distances

A simple two-dimensional point class

The underlying mathematics

Implementing the DistProxy object

Expanding DistProxy to something more useful

Comparing distances with DistProxy

Calculating distances with DistProxy

Preventing the misuse of DistProxy

Performance evaluation

Creative operator overloading and proxy objects

The pipe operator as an extension method

The pipe operator

The infix operator

Further reading

Summary

Concurrency

Understanding the basics of concurrency

What makes concurrent programming hard?

Concurrency and parallelism

Time slicing

Shared memory

Data races

Mutex

Deadlock

Synchronous and asynchronous tasks

Concurrent programming in C++

The thread support library

Threads

Thread states

Protecting critical sections

Avoiding deadlocks

Condition variables

Returning data and handling errors

Tasks

Atomic support in C++

Using shared_ptr in a multithreaded environment

C++ memory model

Instruction reordering

Atomics and memory orders

Lock-free programming

Lock-free queue example

Performance guidelines

Avoid contention

Avoid blocking operations

Number of threads/CPU cores

Thread priorities

Thread affinity

False sharing

Summary

Parallel STL

Importance of parallelism

Parallel algorithms

Implementing parallel std::transform()

Naive implementation

Performance evaluation

Shortcomings of the naive implementation

Divide and conquer

Implementation

Performance evaluation

Implementing parallel std::count_if

Implementing parallel std::copy_if

Approach one – Use a synchronized write position

Inner function

Outer function

Approach two – Split algorithm into two parts

Part one – Copy elements in parallel into the destination range

Part two – Move the sparse range sequentially into a continuous range

Performance evaluation

Parallel STL

Execution policies

Sequenced policy

Parallel policy

Parallel unsequenced policy

Parallel modifications of algorithm

std::accumulate and std::reduce

std::transform_reduce

std::for_each

Parallelizing an index-based for-loop

Combining std::for_each with linear range

Simplifying construction via a wrapper

Executing STL algorithms on the GPU

GPU APIs and parallel operations

Programmable GPUs

Shader programs

STL algorithms and the GPU

Boost Compute

Basic concepts of Boost Compute

OpenCL

Initializing Boost Compute

Transfer a simple transform-reduce algorithm to Boost Compute

The algorithm in standard C++

Transforming the algorithm to Boost Compute

Adapting the circle struct for use with Boost Compute

Converting circle_area_cpu to Boost Compute

The BOOST_COMPUTE_FUNCTION macro

Implementing the transform-reduction algorithm on the GPU

Using predicates with Boost Compute

Using a custom kernel in Boost Compute

Box filter

Implementing the kernel

Parallelizing for two dimensions

Verify GPU computation on the CPU

Summary

Other Books You May Enjoy

Leave a review - let other readers know what you think

Preface

C++ of today provides programmers the ability to write expressive and robust code while still having the ability to target almost any hardware platform or real-time requirements. This makes C++ a unique language. Over the last few years, C++ has turned into a modern language that is more fun to use and with better defaults.

This book aims to give the reader a solid foundation to write efficient applications as well as an insight into strategies for implementing libraries in modern C++. We have tried to take a practical approach to explain how C++ works today, where C++14/C++17 features are a natural part of the language, rather than looking at C++ historically.

This book has been written by us, Viktor and Björn, collaboratively. However, the drafts of each chapter were written individually, and after that, we have worked together to improve the chapters and assemble them into a complete book. Viktor is the main author of chapter 1, 2, 5, 8, 9, and 11. Björn is the main author of chapter 3, 4, 7, and 10. We have worked hard to attain a consistent style throughout the book, and we think that it has been a big advantage to write this book together. Many subjects have been debated and processed for the better.

Who this book is for

This book expects you to have a basic knowledge of C++ and computer architecture and a genuine interest in evolving your skills. Hopefully, by the time you finish this book, you will have gained a few insights into how you can improve your C++ applications, both performance-wise and syntactically. On top of that, we also hope that you will have a fewahamoments.

What this book covers

Chapter 1,A Brief Introduction to C++, introduces some important properties of C++ such as zero-cost abstractions, value semantics, const correctness, explicit ownership, and error handling. It also discusses the drawbacks of C++.

Chapter 2, Modern C++ Concepts, outlines automatic type deduction using auto, lambda functions, move semantics, std::optional, and std::any.

Chapter 3, Measuring Performance, discusses asymptotic complexity and big O notation, practical performance testing, and how to profile your code to find hotspots.

Chapter 4, Data Structures, takes you through the importance of structuring the data so that it can be accessed quickly. STL containers such as std::vector, std::list, std::unordered_map, and std::priority_queue are introduced. Finally, we describe how to iterate over parallel arrays.

Chapter 5, A Deeper Look at Iterators, dives into the concept of iterators, and shows how iterators can go beyond just referring to objects in containers.

Chapter 6, STL Algorithms and Beyond, shows the obvious, and the not so obvious, advantages of STL algorithms over hand rolled for loops. It also takes a look at the limitations of STL algorithms and how the new Ranges library overcomes these limits.

Chapter 7, Memory Management, focuses on safe and efficient memory management. This includes memory ownership, RAII, smart pointers, stack memory, dynamic memory, and custom memory allocators.

Chapter 8, Metaprogramming and Compile-Time Evaluation, explains metaprogramming concepts such as constexpr, heterogeneous containers, type_traits, std::enable_if, and std::is_detected. It also gives practical examples of metaprogramming use cases, such as reflection.

Chapter 9, Proxy Objects and Lazy Evaluation, explores how proxy objects can be used to perform under-the-hood optimizations while preserving clean syntax. Additionally, some creative uses of operator-overloading are demonstrated.

Chapter 10, Concurrency, covers the fundamentals of concurrent programming, including parallel execution, shared memory, data races, and deadlocks. It also includes an introduction to the C++ thread support library, the atomic library, and the C++ memory model.

Chapter 11, Parallel STL, starts by showing the complexity of writing parallel algorithms. It then demonstrates how to utilize STL algorithms in a parallel context using the parallel extensions for STL and Boost Compute.

To get the most out of this book

To get the most out of this book, you need to have a basic knowledge of C++. It's preferable if you have already been facing problems related to performance and are now looking for new tools and practices to have ready the next time you need to work with performance and C++.

There are a lot of code examples in this book. Some are taken from the real world, but most of them are artificial or vastly simplified examples to prove a concept rather than providing you with production-ready code. We have put all the code examples in source files divided by chapter so that it is fairly easy to find the examples you want to experiment with. If you open up the source code files, you will note that we have replaced most of the main() functions from the examples with test cases written with Google Test framework. We hope that this will help you rather than confuse you. It allowed us towrite helpful descriptions for each example, and it also makes it easier to run all the examples from one chapter at once.

In order to compile and run the examples, you will need the following:

A computer

An operation system (we have verified the examples on Windows and macOS)

A compiler (we have been using Clang, GCC, and 

Microsoft Visual C++)

CMake

The CMake script provided with the example code will download and install further dependencies such as Boost, OpenCL, and Google Test.

During the writing of this book, it has been of great help for us to use Compiler Explorer, which is available at https://godbolt.org/. Compiler Explorer is an online compiler service that lets you try various compilers and versions. Try it out if you haven't already!

Download the example code files

You can download the example code files for this book from your account at www.packtpub.com. If you purchased this book elsewhere, you can visit www.packtpub.com/support and register to have the files emailed directly to you.

You can download the code files by following these steps:

Log in or register at

www.packtpub.com

.

Select the

SUPPORT

tab.

Click on

Code Downloads & Errata

.

Enter the name of the book in the

Search

box and follow the onscreen instructions.

Once the file is downloaded, please make sure that you unzip or extract the folder using the latest version of:

WinRAR/7-Zip for Windows

Zipeg/iZip/UnRarX for Mac

7-Zip/PeaZip for Linux

The code bundle for the book is also hosted on GitHub athttps://github.com/PacktPublishing/Cpp-High-Performance. We also have other code bundles from our rich catalog of books and videos available athttps://github.com/PacktPublishing/. Check them out!

Conventions used

There are a number of text conventions used throughout this book.

CodeInText: Indicates code words in text, folder names, filenames, file extensions, dummy URLs, and user input. Here is an example: "The keyword constexpr was introduced in C++11."

A block of code is set as follows:

#include <iostream>auto main() -> int { std::cout << "High Performance C++\n";}

When we wish to draw your attention to a particular part of a code block, the relevant lines or items are set in bold:

#include <iostream>auto main() -> int {

std::cout << "High Performance C++\n";

}

Any command-line input or output is written as follows:

$ clang++ -std=c++17 high_performance.cpp

$ ./a.out$ High Performance C++

Bold: Indicates a new term, an important word, or words that you see onscreen. For example, words in menus or dialog boxes appear in the text like this. Here is an example: "Select System info from the Administration panel."

Warnings or important notes appear like this.
Tips and tricks appear like this.

Get in touch

Feedback from our readers is always welcome.

General feedback: Email [email protected] and mention the book title in the subject of your message. If you have questions about any aspect of this book, please email us at [email protected].

Errata: Although we have taken every care to ensure the accuracy of our content, mistakes do happen. If you have found a mistake in this book, we would be grateful if you would report this to us. Please visit www.packtpub.com/submit-errata, selecting your book, clicking on the Errata Submission Form link, and entering the details.

Piracy: If you come across any illegal copies of our works in any form on the Internet, we would be grateful if you would provide us with the location address or website name. Please contact us at [email protected] with a link to the material.

If you are interested in becoming an author: If there is a topic that you have expertise in and you are interested in either writing or contributing to a book, please visit authors.packtpub.com.

Reviews

Please leave a review. Once you have read and used this book, why not leave a review on the site that you purchased it from? Potential readers can then see and use your unbiased opinion to make purchase decisions, we at Packt can understand what you think about our products, and our authors can see your feedback on their book. Thank you!

For more information about Packt, please visit packtpub.com.

A Brief Introduction to C++

This chapter will introduce some of the features of C++ that we think are important for writing robust and high performance applications. We will also discuss advantages and disadvantages of C++ over languages based upon a garbage collector. Last, we will look at some examples of how to handle exceptions and resources.

Why C++?

We begin this book by exploring some of the reasons for using C++ today. In short, C++ is a highly portable language which offers zero-cost abstractions. Furthermore, we believe that C++ provides programmers with the ability to write and manage large, expressive, and robust code bases. Let's explore the meaning of each of these properties.

Zero-cost abstractions

Active code bases grow. The more developers working on a code base, the larger the code base becomes. We need abstractions such as functions, classes, data structures, layers and so on in order to manage the complexity of a large-scale code base. But constantly adding abstractions and new levels of indirection comes at a price — efficiency. This is where zero-cost abstractions plays its role. A lot of the abstractions offered by C++ comes at a very low price. At a minimum, C++ offers efficient alternatives at hot spots where performance really is a concern.

With C++ you are free to talk about memory addresses and other computer related low-level terms when needed. However, in a large-scale software project it is desirable to express code in terms that deals with whatever the application is doing, and let the libraries handle the computer related terminology. The source code of a graphics application may deal with pencils, colors, and filters, whereas a game may deal with mascots, castles, and mushrooms. Low-level computer-related terms such as memory addresses can stay hidden in C++ library code where performance is critical.

By library code, we refer to code whose concepts are not strictly related to the application. The line between library code and application code can be blurry though, and libraries are often built upon other libraries. An example could be the container algorithms provided in the Standard Template Library (STL) of C++ or a general-purpose math library.

Abstractions in other languages

Most programming languages are based on abstractions, which are transformed into machine code to be executed by the CPU. C++ has evolved into a highly expressive language just like many of the other popular programming languages of today. What distinguishes C++ from most other languages is that, while the other languages have implemented these abstractions at the cost of runtime performance, C++ has always strived to implement its abstractions at zero cost at runtime. This doesn't mean that an application written in C++ is by default faster than the equivalent in, say, C#. Rather, it means that by using C++, you'll have explicit control of the emitted machine code instructions and memory footprint if needed.

To be fair, optimal performance is very rarely required today and compromising performance for lower compilation times, garbage collection, or safety, like other languages do, is in many cases more reasonable.

Portability

C++ has been a popular and comprehensive language for a long time. It's highly compatible with C and very little has been deprecated in the language, for better or worse. The history and design of C++ has made it to a highly portable language, and the evolution of modern C++ has ensured that it will stay that way for a long time to come. C++ is a living language and compiler vendors are currently doing a remarkable job to implement new language features rapidly.

Robustness

In addition to performance, expressiveness, and portability, C++ offers a set of language features that gives the programmer the ability to write robust code.

In our experience, robustness does not refer to strength in the programming language itself – it's possible to write robust code in any language. However, strict ownership of resources, const correctness, value semantics, type safety, and deterministic destruction of objects are some of the features offered by C++ that makes it easier to write robust code. That is, the ability to write functions, classes, and libraries that are easy to use and hard to misuse.

C++ of today

To sum it up, C++ of today provides programmers the ability to write an expressive and robust code base while still having the ability to target almost any hardware platform or real-time requirements. Of the most commonly used languages today, C++ is the only one that gives all of these properties.

The aim of this book

This book aims to give the reader a solid foundation to write efficient applications as well as an insight into strategies for implementing the libraries in modern C++. We have tried to take a practical approach to explain how C++ works today where C++14/C++17 features are a natural part of the language, rather than looking at C++ historically.

Expected knowledge of the reader

This book expects you to have a basic knowledge of C++ and computer architecture, and a genuine interest in evolving your skills. Hopefully, by the time you finish this book, you will have gained a few insights into how you can improve your C++ applications, both performance-wise and syntactically. On top of that, we also hope that you will have a few aha moments.

C++ compared with other languages

A multitude of application types, platforms, and programming languages have emerged since C++ was first released. Still, C++ is a widely used language, and its compilers are available for most platforms. The major exception, as of today, is the web platform, where JavaScript and its related technologies are the foundation. However, the web platform is evolving into being able to execute what was previously only possible in desktop applications, and in that context C++ has found its way into web applications using technologies such as Emscripten/asm.js and web assembly.

Non-performance-related C++ language features

In some discussions about C++ versus other languages, it's concluded that C++ should only be used if performance is a major concern. Otherwise, it's said to just increase the complexity of the code base due to manual memory handling, which may result in memory leaks and hard-to-track bugs.

This may have been true several C++ versions ago, but a modern C++ programmer relies on the provided containers and smart pointer types, which are part of the STL.

We would here like to highlight two  powerful features of C++ related to robustness rather than performance, that we think are easily overlooked: value semantics and const correctness.

Object ownership and garbage collection in C++

Except in very rare situations, a C++ programmer should leave the memory handling to containers and smart pointers and never have to rely on manual memory handling.

To put it clearly, the garbage collection model in Java could almost be emulated in C++ by using std::shared_ptr for every object. Note that garbage-collecting languages don't use the same algorithm for allocation tracking as std::shared_ptr. The std::shared_ptr is a smart pointer based on a reference-counting algorithm that will leak memory if objects have cyclic dependencies. Garbage-collecting languages have more sophisticated methods that can handle and free cyclic dependent objects.

However, rather than relying on a garbage collector, forcing a strict ownership delicately avoids subtle bugs that may result from sharing objects by default, as in the case of Java.

If a programmer minimize shared ownership in C++, the resulting code is easier to use and harder to abuse, as it can force the user of the class to use it as it is intended.

Drawbacks of C++

Comparing C++ with other programming languages wouldn't be fair without mentioning some of its drawbacks. As mentioned earlier, C++ has more concepts to learn, and is therefore harder to use correctly and to its full potential. However, if a programmer can master C++, the higher complexity turns into an advantage and the code base becomes more robust and performs better.

There are, nonetheless, some shortcomings of C++, which are simply just shortcomings. The most severe of those shortcomings are long compilation times, the reliance on the manual handling of forward declarations, header/source files, and the complexity of importing libraries.

This is mainly a result of C++ relying on an outdated import system where imported headers are simply pasted into whatever includes them. At the time of writing this book, a modern module-based import system is up for standardization, but until the standardized C++ version becomes available, project management remains very tedious.

Another apparent drawback of C++ is the lack of provided libraries. While other languages usually come with all the libraries needed for most applications, such as graphics, user interfaces, networking, threading, resource handling, and so on, C++ provides, more or less, nothing more than the bare minimum of algorithms, threads, and, as of C++17, file system handling. For everything else, programmers have to rely on external libraries.

To summarize, although C++ has a steeper learning curve than most other languages, if used correctly, the robustness of C++ is an advantage compared to many other languages. So, despite the outdated import/library system of C++,  we believe that C++ is a well suited language for large-scale projects, even for projects where performance is not the highest priority.

Class interfaces and exceptions

Before diving deeper into the concepts of C++ high performance, we would like to emphasize some concepts that you should not compromise on when writing C++ code.