← SEARCHABLE ARCHIVE
C / C++ · 2026-08-15

C++ 從基礎到精通 — 第 22 講

以資料配置、快取與 pmr 設計記憶體成本

INTERACTIVE READING MODE →

本部落格文章以教學為目的撰寫。 內容可能有誤,請搭配目標編譯器與標準函式庫文件確認。

效能不只由運算次數決定。物件配置、存取順序與配置頻率會影響 CPU cache 與整體 throughput。

連續資料較容易利用 Cache

struct Particle
{
    float X, Y, Z;
    float VelocityX, VelocityY, VelocityZ;
    bool Active;
};

std::vector<Particle> particles;

當每次處理都使用大部分欄位時,AoS 簡單且具良好區域性。但只更新位置時,未使用欄位也可能被載入 cache line。

struct ParticlePositions
{
    std::vector<float> X, Y, Z;
};

SoA 讓相同欄位連續排列,有利於批次處理與 SIMD,但會增加單一物件 API 的複雜度。

依生命週期設計配置

std::array<std::byte, 4096> buffer;
std::pmr::monotonic_buffer_resource arena(buffer.data(), buffer.size());
std::pmr::vector<std::pmr::string> names(&arena);

names.emplace_back("Knight");
names.emplace_back("Mage");

PMR 容器能在執行期注入 memory resource。monotonic_buffer_resource 只向前配置並一次釋放全部內容,適合共享同一短生命週期的臨時資料。

Resource 必須比所有使用它的容器與元素活得更久。若 arena 先被銷毀,容器會參考無效記憶體。

reserve 是再配置政策

std::vector<Entity> entities;
entities.reserve(expectedCount);

已知預估大小時,reserve 可減少重複配置與移動;估計過大則長期占用未使用記憶體。再配置也會使地址與 iterator 失效,長期外部參考可改用 index 或帶 generation 的 handle。

不要在沒有測量時改變 layout。以代表性 workload 比較 wall time、CPU time、配置次數、peak memory 與 cache miss,並重新驗證正確性。

好的記憶體設計不是最聰明的 allocator,而是明確表達資料生命週期與存取模式,並以最簡單的所有權模型達成量測目標。