访问变体与访问单个元素的性能
我正在试验一种用于任意精度算术的算法,并希望使用std::array. 并且由于我std::vector用作长整数的动态存储,因此我决定使用std::variant<std::array, std::vector>此短整数优化。我不确定 std::visit 的性能,所以我使用 Google 基准测试了它。事实证明,它std::visit比正常直接访问容器内的元素要快。
std::visit在 MSVC 上作为 switch case 实现,除了std::variant由于标记联合而具有更大的内存占用之外,怎么可能std::variant更快?有人对此有解释吗?
测试代码:
#include <array>
#include <variant>
#include "benchmark/benchmark.h"
static void VecOf_VariantOf_Vec_Arr(benchmark::State& state) {
using ST = std::array<uint8_t, 20>;
std::vector<std::variant<std::vector<uint8_t>, ST>> vec;
vec.reserve(1024 * 1024);
for (auto i = 0u; i < 1024 * 1024; ++i)
vec.emplace_back(std::in_place_type<ST>);
for (auto idx = 0u; auto _ : state) {
std::visit([idx]<typename T0>(T0& e)
{
if constexpr (std::same_as<T0, ST>)
e.fill(static_cast<uint8_t>(idx));
}, vec[idx]);
idx += 1;
idx %= vec.size();
benchmark::DoNotOptimize(vec);
benchmark::DoNotOptimize(idx);
benchmark::ClobberMemory();
}
}
BENCHMARK(VecOf_VariantOf_Vec_Arr);
static void VecOf_Arr(benchmark::State& state) {
std::vector<std::array<uint8_t, 20>> vec;
vec.reserve(1024 * 1024);
for (auto i = 0u; i < 1024 * 1024; ++i)
vec.emplace_back();
for (auto idx = 0u; auto _ : state) {
auto& e = vec[idx];
e.fill(static_cast<uint8_t>(idx));
idx += 1;
idx %= vec.size();
benchmark::DoNotOptimize(vec);
benchmark::DoNotOptimize(idx);
benchmark::ClobberMemory();
}
}
BENCHMARK(VecOf_Arr);
MSVC 上的结果:
海湾合作委员会的结果:
在 Clang 上的结果:
这是基准