C++ 性能优化
概述
性能优化是C++编程的重要方面。本章介绍内存管理、算法优化、编译器优化、性能测量等关键技术,帮助开发者写出高效的C++程序。
📊 性能测量
基准测试
cpp
#include <iostream>
#include <chrono>
#include <vector>
#include <algorithm>
class Timer {
private:
std::chrono::high_resolution_clock::time_point start_;
std::string name_;
public:
Timer(const std::string& name) : name_(name) {
start_ = std::chrono::high_resolution_clock::now();
}
~Timer() {
auto end = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start_);
std::cout << name_ << " 耗时: " << duration.count() << " 微秒" << std::endl;
}
};
void memoryAccessTest() {
const size_t SIZE = 1024 * 1024;
std::vector<int> data(SIZE, 1);
// 顺序访问
{
Timer timer("顺序访问");
int sum = 0;
for (size_t i = 0; i < SIZE; ++i) {
sum += data[i];
}
}
// 跳跃访问
{
Timer timer("跳跃访问");
int sum = 0;
for (size_t i = 0; i < SIZE; i += 16) {
sum += data[i];
}
}
}🧠 内存优化
对象池模式
cpp
#include <vector>
#include <memory>
template<typename T>
class ObjectPool {
private:
std::vector<std::unique_ptr<T>> pool_;
std::vector<T*> available_;
public:
T* acquire() {
if (available_.empty()) {
pool_.push_back(std::make_unique<T>());
return pool_.back().get();
}
T* obj = available_.back();
available_.pop_back();
return obj;
}
void release(T* obj) {
available_.push_back(obj);
}
};
// 使用示例
void objectPoolDemo() {
struct ExpensiveObject {
std::vector<int> data;
ExpensiveObject() : data(1000, 42) {}
};
ObjectPool<ExpensiveObject> pool;
// 对象池版本
{
Timer timer("对象池");
for (int i = 0; i < 1000; ++i) {
auto* obj = pool.acquire();
// 使用对象
pool.release(obj);
}
}
// 直接创建版本
{
Timer timer("直接创建");
for (int i = 0; i < 1000; ++i) {
auto obj = std::make_unique<ExpensiveObject>();
// 使用对象
}
}
}内存池分配器
cpp
class MemoryPool {
private:
char* memory_;
size_t block_size_;
std::vector<void*> free_blocks_;
public:
MemoryPool(size_t block_size, size_t num_blocks)
: block_size_(block_size) {
memory_ = new char[block_size * num_blocks];
for (size_t i = 0; i < num_blocks; ++i) {
free_blocks_.push_back(memory_ + i * block_size);
}
}
~MemoryPool() {
delete[] memory_;
}
void* allocate() {
if (free_blocks_.empty()) return nullptr;
void* block = free_blocks_.back();
free_blocks_.pop_back();
return block;
}
void deallocate(void* ptr) {
free_blocks_.push_back(ptr);
}
};⚡ 算法优化
容器选择
cpp
#include <set>
#include <unordered_set>
#include <vector>
void containerComparison() {
const size_t SIZE = 100000;
const int SEARCH_VALUE = SIZE / 2;
std::vector<int> vec(SIZE);
std::iota(vec.begin(), vec.end(), 0);
std::set<int> ordered_set(vec.begin(), vec.end());
std::unordered_set<int> hash_set(vec.begin(), vec.end());
// 线性查找
{
Timer timer("vector线性查找");
auto it = std::find(vec.begin(), vec.end(), SEARCH_VALUE);
}
// 二分查找
{
Timer timer("vector二分查找");
bool found = std::binary_search(vec.begin(), vec.end(), SEARCH_VALUE);
}
// 有序集合查找
{
Timer timer("set查找");
auto it = ordered_set.find(SEARCH_VALUE);
}
// 哈希表查找
{
Timer timer("unordered_set查找");
auto it = hash_set.find(SEARCH_VALUE);
}
}循环优化
cpp
void loopOptimization() {
const size_t SIZE = 1000;
std::vector<std::vector<int>> matrix(SIZE, std::vector<int>(SIZE, 1));
// 按行访问(缓存友好)
{
Timer timer("按行访问");
long long sum = 0;
for (size_t i = 0; i < SIZE; ++i) {
for (size_t j = 0; j < SIZE; ++j) {
sum += matrix[i][j];
}
}
}
// 按列访问(缓存不友好)
{
Timer timer("按列访问");
long long sum = 0;
for (size_t j = 0; j < SIZE; ++j) {
for (size_t i = 0; i < SIZE; ++i) {
sum += matrix[i][j];
}
}
}
// 循环展开
{
Timer timer("循环展开");
long long sum = 0;
for (size_t i = 0; i < SIZE; ++i) {
size_t j;
for (j = 0; j + 4 <= SIZE; j += 4) {
sum += matrix[i][j] + matrix[i][j+1] +
matrix[i][j+2] + matrix[i][j+3];
}
for (; j < SIZE; ++j) {
sum += matrix[i][j];
}
}
}
}🔧 编译器优化
内联和常量优化
cpp
// 内联函数
inline int fastAdd(int a, int b) {
return a + b;
}
// 常量表达式
constexpr int factorial(int n) {
return n <= 1 ? 1 : n * factorial(n - 1);
}
void compilerOptimizations() {
const int ITERATIONS = 10000000;
// 函数调用
{
Timer timer("函数调用");
int sum = 0;
for (int i = 0; i < ITERATIONS; ++i) {
sum = fastAdd(sum, i);
}
}
// 直接计算
{
Timer timer("直接计算");
int sum = 0;
for (int i = 0; i < ITERATIONS; ++i) {
sum += i;
}
}
// 编译时计算
constexpr int result = factorial(10);
std::cout << "编译时计算结果: " << result << std::endl;
}分支预测优化
cpp
void branchPrediction() {
const size_t SIZE = 1000000;
std::vector<int> data(SIZE);
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dis(0, 100);
for (auto& val : data) {
val = dis(gen);
}
const int THRESHOLD = 50;
// 随机数据(分支难预测)
{
Timer timer("分支不可预测");
int count = 0;
for (int value : data) {
if (value > THRESHOLD) {
count++;
}
}
}
// 排序后(分支可预测)
std::sort(data.begin(), data.end());
{
Timer timer("分支可预测");
int count = 0;
for (int value : data) {
if (value > THRESHOLD) {
count++;
}
}
}
// 无分支版本
{
Timer timer("无分支版本");
int count = 0;
for (int value : data) {
count += (value > THRESHOLD);
}
}
}🚀 高级优化
并行算法
cpp
#include <execution>
#include <numeric>
void parallelOptimization() {
const size_t SIZE = 10000000;
std::vector<int> data(SIZE);
std::iota(data.begin(), data.end(), 1);
// 串行求和
{
Timer timer("串行求和");
long long sum = std::accumulate(data.begin(), data.end(), 0LL);
}
// 并行求和(C++17)
#ifdef __cpp_lib_parallel_algorithm
{
Timer timer("并行求和");
long long sum = std::reduce(std::execution::par, data.begin(), data.end(), 0LL);
}
#endif
}缓存优化
cpp
// 数组结构 vs 结构数组
struct Point3D_AoS {
float x, y, z;
};
struct Points3D_SoA {
std::vector<float> x, y, z;
Points3D_SoA(size_t size) : x(size), y(size), z(size) {}
};
void cacheOptimization() {
const size_t SIZE = 1000000;
std::vector<Point3D_AoS> aos_points(SIZE);
Points3D_SoA soa_points(SIZE);
// AoS访问(可能缓存不友好)
{
Timer timer("AoS访问");
float sum = 0;
for (const auto& point : aos_points) {
sum += point.x;
}
}
// SoA访问(缓存友好)
{
Timer timer("SoA访问");
float sum = 0;
for (float x : soa_points.x) {
sum += x;
}
}
}演示程序
cpp
int main() {
std::cout << "=== C++ 性能优化演示 ===" << std::endl;
std::cout << "\n1. 内存访问模式:" << std::endl;
memoryAccessTest();
std::cout << "\n2. 对象池优化:" << std::endl;
objectPoolDemo();
std::cout << "\n3. 容器选择:" << std::endl;
containerComparison();
std::cout << "\n4. 循环优化:" << std::endl;
loopOptimization();
std::cout << "\n5. 编译器优化:" << std::endl;
compilerOptimizations();
std::cout << "\n6. 分支预测:" << std::endl;
branchPrediction();
std::cout << "\n7. 并行优化:" << std::endl;
parallelOptimization();
std::cout << "\n8. 缓存优化:" << std::endl;
cacheOptimization();
return 0;
}总结
优化策略
- 测量优先: 先测量再优化
- 算法为王: 选择正确的算法和数据结构
- 内存意识: 考虑缓存友好性和内存访问模式
- 编译器配合: 利用编译器优化特性
性能要点
| 技术 | 影响 | 适用场景 |
|---|---|---|
| 缓存优化 | 高 | 大数据处理 |
| 内存池 | 中 | 频繁分配 |
| 并行算法 | 高 | CPU密集型 |
| 分支预测 | 中 | 条件密集型 |
最佳实践
- 选择合适的容器和算法
- 考虑内存布局和访问模式
- 利用编译器优化选项
- 在关键路径上进行细致优化
- 平衡代码可读性和性能
性能优化需要深入理解计算机体系结构和编译器工作原理,是高级C++开发的重要技能。