簡體   English   中英

理解 std::map::insert & emplace with hint

[英]Understand std::map::insert & emplace with hint

map插入比較

問題> 我試圖理解insert & emplace的用法,並在std::map中引入提示。 在接下來的測試中,在我看來,老式insert是最快的。 我在這里做錯了什么嗎?

謝謝

static void MapEmplaceWithHint(benchmark::State& state) {
    std::vector<int> v{12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
    std::map<int, int> mapInt;
    auto where(std::end(mapInt));
        
  for (auto _ : state) {
   for (const auto &n : v) { // Items in non-incremental order
        where = mapInt.emplace_hint(where, n, n+1);
    }
  }
}
BENCHMARK(MapEmplaceWithHint);

static void MapInsertWithHint(benchmark::State& state) {
    std::vector<int> v{12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
    std::map<int, int> mapInt;
    auto where(std::end(mapInt));
        
  for (auto _ : state) {
   for (const auto &n : v) { // Items in non-incremental order
        where = mapInt.insert(where, {n, n+1});
    }
  }
}
BENCHMARK(MapInsertWithHint);

static void MapInsertNoHint(benchmark::State& state) {
    std::vector<int> v{12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
    std::map<int, int> mapInt;
        
  for (auto _ : state) {
   for (const auto &n : v) { // Items in non-incremental order
        mapInt.insert({n, n+1});
    }
  }
}
BENCHMARK(MapInsertNoHint);

static void MapReverseInsertNoHint(benchmark::State& state) {
    std::vector<int> v{0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12};
    std::map<int, int> mapInt;
        
  for (auto _ : state) {
   for (const auto &n : v) { // Items in incremental order
        mapInt.insert({n, n+1});
    }
  }
}
BENCHMARK(MapReverseInsertNoHint);

static void MapEmplaceNoHint(benchmark::State& state) {
    std::vector<int> v{12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
    std::map<int, int> mapInt;
        
  for (auto _ : state) {
   for (const auto &n : v) { // Items in non-incremental order
        mapInt.emplace(n, n+1);
    }
  }
}
BENCHMARK(MapEmplaceNoHint);

在此處輸入圖像描述

首先,讓我們創建一個比 12 個整數更有意義的數據集:

  std::vector<int> v(10000);
  std::iota(v.rbegin(), v.rend(), 0);

所有功能的結果現在更具可比性: https://quick-bench.com/q/HW3eYL1RaFMCJvDdGLBJwEbDLdg

在此處輸入圖像描述

然而,還有更糟糕的事情。 請注意,循環遍歷state會使其多次執行相同的操作以測量平均時間。 但是,由於您正在重復使用相同的emplace ,因此在第一次循環迭代失敗后每次insert或放置都會失敗,因此您主要測量失敗插入的時間,其中hint無濟於事。

測試用例應該更像這樣:

  std::vector<int> v(1000);
  std::iota(v.rbegin(), v.rend(), 0);

  for (auto _ : state) {
    std::map<int, int> mapInt;
    auto where(std::end(mapInt));
        
   for (const auto &n : v) { // Items in non-incremental order
        where = mapInt.emplace_hint(where, n, n+1);
    }
  }

有了這個,提示開始閃耀(必須將數據限制為 1000,否則我會超時): https://quick-bench.com/q/2cR4zU_FZ5HQ6owPj9Ka_y9FtZE 在此處輸入圖像描述

我不確定基准測試是否正確,但快速瀏覽一下裝配表明插入件沒有完全優化,所以它有可能足夠好。

正如Ted Lyngmo 所注意到的,帶有hinttry_emplace()往往表現得(稍微)更好:
https://quick-bench.com/q/evwcw4ovP20qJzfsyl6M-_37HzI 在此處輸入圖像描述

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM