【问题标题】:Google Benchmark BaseClass Initialization happens before static variable assignment causes problemGoogle Benchmark Ba​​seClass 初始化发生在静态变量分配导致问题之前
【发布时间】:2023-04-02 07:50:01
【问题描述】:

我想使用 google benchmark 来运行我的代码,其中包含一个静态全局变量。在基准测试的基类中,我需要读取这个变量来执行一些设置。但是当初始化基准基类时,那个静态变量还没有初始化,会导致问题。

下面的最小复制示例包含三个文件:test.htest.ccbenchmark_main.ccbenchmark_main.cc 包含基准基类 Init。它的构造函数读取data 变量。但是此时data变量还是空的。

问题:有没有办法让data 变量初始化发生在基类初始化之前?也欢迎任何其他解决方法。

测试.h

#include <array>
#include <vector>

using namespace std;

const vector<int>& func(int);

test.cc

#include "test.h"

const array<vector<int>,5> data = {
        vector<int>({1}),
        {2,3},
        {4,5},
        {6,7},
        {8}
};

const vector<int>& func(int index) {
        return data[index];
}

benchmark_main.cc

#include <benchmark/benchmark.h>
#include <iostream>
#include "test.h"

class Init: public benchmark::Fixture {
protected:
public:
    Init() {
        std::cout << func(1)[0] << '\n';
    }
};

BENCHMARK_F(Init, A)(benchmark::State &state) {
  for (auto _ : state)
    std::cout << func(1)[0] << '\n';
}

BENCHMARK_MAIN();

【问题讨论】:

  • 不要将using namespace std; 放在头文件中。而且它不是静态数据。它位于本地文件的全局命名空间中。

标签: c++ microbenchmark google-benchmark


【解决方案1】:

您的问题是 C++ 中的全局变量在不同的翻译单元(即 .cc 文件)之间具有未定义的初始化顺序。

我看到了一些解决方法:

  1. 将代码从 test.cc 移动到 benchmark_main.cc 的顶部,因为全局变量在单个文件中按声明顺序进行初始化。在本示例中这很简单,但在大型项目中并不容易。
  2. data 全局变量改为func() 中的静态变量。这可能会在一定程度上影响性能,因为它会在每次调用函数时检查静态是否已初始化。
  3. 您可以对编译器进行特定的调整来修改全局变量的初始化顺序。例如:https://docs.microsoft.com/en-us/cpp/preprocessor/init-seg?view=msvc-160
  4. 您可以更直接地使用 API 来避免使用全局变量,而不是使用 BENCHMARK_F 宏。 Google benchmark custom main 可能会对此有所帮助。

【讨论】:

  • 感谢您的建议!解决方案 1 和 2 不起作用,因为我不想因为实施基准测试而更改我的代码。 3 看起来很有希望,但它也需要更改代码。我决定采用解决方案 4。我最终编写了一个用于初始化工作的函数,并使用 BENCHMARK 而不是 BENCHMARK_F。
最近更新 更多