Namespaces
Variants

std::pmr:: monotonic_buffer_resource

From cppreference.net
Memory management library
( exposition only* )
Allocators
Uninitialized memory algorithms
Constrained uninitialized memory algorithms
Memory resources
Uninitialized storage (until C++20)
( until C++20* )
( until C++20* )
( until C++20* )

Garbage collector support (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
ヘッダーで定義 <memory_resource>
class monotonic_buffer_resource : public std:: pmr :: memory_resource ;
(C++17 以降)

std::pmr::monotonic_buffer_resource クラスは、確保されたメモリをリソースが破棄される時のみ解放する特殊目的のメモリリソースクラスです。これは、メモリを使用して少数のオブジェクトを構築し、その後すべて一度に解放される状況において、非常に高速なメモリ割り当てを目的としています。

monotonic_buffer_resource は初期バッファを指定して構築できます。初期バッファが存在しない場合、またはバッファが枯渇した場合、構築時に供給された upstream memory resource から追加のバッファが取得されます。取得されるバッファのサイズは等比数列に従って増加します。

monotonic_buffer_resource はスレッドセーフではありません。

目次

メンバー関数

monotonic_buffer_resource を構築する
(public member function)
[virtual]
monotonic_buffer_resource を破棄し、割り当てられたすべてのメモリを解放する
(virtual public member function)
operator=
[deleted]
コピー代入演算子は削除済み。 monotonic_buffer_resource はコピー代入不可
(public member function)
公開メンバ関数
割り当てられたすべてのメモリを解放する
(public member function)
上流メモリリソースへのポインタを返す
(public member function)
保護メンバ関数
[virtual]
メモリを割り当てる
(virtual protected member function)
[virtual]
何もしない(no-op)
(virtual protected member function)
[virtual]
他の std::pmr::memory_resource との等価性を比較する
(virtual protected member function)

このプログラムは、以下のアロケータを使用して巨大な双方向リンクリストを作成する時間を計測します:

  • デフォルト標準アロケータ、
  • デフォルト pmr アロケータ、
  • pmr アロケータ(単調リソース使用、明示的メモリバッファなし)、
  • pmr アロケータ(単調リソース使用、外部メモリバッファ(スタック上))。
#include <array>
#include <chrono>
#include <cstddef>
#include <iomanip>
#include <iostream>
#include <list>
#include <memory_resource>
template<typename Func>
auto benchmark(Func test_func, int iterations)
{
    const auto start = std::chrono::system_clock::now
(注:指定された条件により、HTMLタグ・属性、タグ内のC++識別子は翻訳対象外のため、元のテキストを保持しています)();
    while (iterations-- > 0)
        test_func();
    const auto stop = std::chrono::system_clock::now
(注:指定された条件により、HTMLタグ・属性、タグ内のC++識別子、C++専門用語は翻訳対象外のため、元のテキストを保持しています)();
    const auto secs = std::chrono::duration<double>(stop - start);
    return secs.count();
}
int main()
{
    constexpr int iterations{100};
    constexpr int total_nodes{2'00'000};
    auto default_std_alloc = [total_nodes]
    {
        std::list<int> list;
        for (int i{}; i != total_nodes; ++i)
            list.push_back(i);
    };
    auto default_pmr_alloc = [total_nodes]
    {
        std::pmr::list
(注:元のテキストはC++の専門用語であり、HTMLタグと属性も含まれているため、翻訳対象外です。表示は元のまま維持されます)<int> list;
        for (int i{}; i != total_nodes; ++i)
            list.push_back(i);
    };
    auto pmr_alloc_no_buf = [total_nodes]
    {
        std::pmr::monotonic_buffer_resource mbr;
        std::pmr::polymorphic_allocator
(注:HTMLタグと属性、C++固有の用語は翻訳せず、元のフォーマットを保持しています)<int> pa{&mbr};
        std::pmr::list
(注:元のテキストはC++の専門用語であり、HTMLタグと属性は保持されています。翻訳対象となる自然言語のテキストが含まれていないため、出力は入力と同じになります)<int> list{pa};
        for (int i{}; i != total_nodes; ++i)
            list.push_back(i);
    };
    auto pmr_alloc_and_buf = [total_nodes]
    {
        std::array<std::byte, total_nodes * 32> buffer; // すべてのノードを格納するのに十分なサイズ
        std::pmr::monotonic_buffer_resource mbr{buffer.data(), buffer.size()};
        std::pmr::polymorphic_allocator<int> pa{&mbr};
        std::pmr::list
(注:元のテキストはC++の専門用語であり、HTMLタグと属性も保持されているため、翻訳対象外です。表示されるテキスト「std::pmr::list」は変更されていません。)<int> list{pa};
        for (int i{}; i != total_nodes; ++i)
            list.push_back(i);
    };
    const double t1 = benchmark(default_std_alloc, iterations);
    const double t2 = benchmark(default_pmr_alloc, iterations);
    const double t3 = benchmark(pmr_alloc_no_buf , iterations);
    const double t4 = benchmark(pmr_alloc_and_buf, iterations);
    std::cout << std::fixed << std::setprecision(3)
              << "t1 (デフォルト std アロケータ): " << t1 << " 秒; t1/t1: " << t1/t1 << '\n'
              << "t2 (デフォルト pmr アロケータ): " << t2 << " 秒; t1/t2: " << t1/t2 << '\n'
              << "t3 (pmr alloc バッファなし): " << t3 << " 秒; t1/t3: " << t1/t3 << '\n'
              << "t4 (pmr alloc and buf): " << t4 << " 秒; t1/t4: " << t1/t4 << '\n';
}

出力例:

t1 (デフォルト std アロケータ): 0.720 秒; t1/t1: 1.000
t2 (デフォルト pmr アロケータ): 0.915 秒; t1/t2: 0.787
t3 (pmr アロケータ バッファなし): 0.370 秒; t1/t3: 1.945
t4 (pmr アロケータ バッファあり): 0.247 秒; t1/t4: 2.914