将一个 STL 向量高效地分配给另一个 STL 向量(WSL 问题)

Efficient assignment of a STL vector to another STL vector (WSL Issue)

我对完成 STL 向量分配的时间有疑问。

上下文是: 我正在将一个二进制文件读入 std::vector,如下所示:

std::vector<float> read_file(const std::string &file_path) {

    std::ifstream stream(file_path);

    if (!stream.good()) {
        std::cout << "Cannot open file located at: " << file_path << std::endl;
        return std::vector<float>();
    }

    stream.seekg(0, std::ios_base::end);    
    auto size = stream.tellg();
    stream.seekg(0, std::ios_base::beg);

    std::vector<float> values(size / sizeof(float));
    stream.read((char*) &values[0], size);

    stream.close();

    return values;
}

我有 128 个二进制文件,每个文件都包含 ~2.500.000 个浮点数 值。

最终我会得到 128 x std::vector<float> 个向量。但是我希望它们存储在一个 list/vector (矩阵应该说)中,它变成这个数据结构: std::vector<std::vector<float>>.

问题是:

示例 1: 此代码片段的执行时间将花费 ~700ms:

std::vector<float> data;
for (int i = 1; i <= 128; ++i) {
    data = read_file(getFile(i));
}

示例 2: 但是,此代码片段的执行时间将花费 ~2000 毫秒:

std::vector<std::vector<float>> data(128);
for (auto i = 1; i <= 128; ++i) {
    data[i-1] = read_file(getFile(i));
}

根据我的理解,如果右侧是vector&&,赋值将执行移动操作,如果右侧是const vector&,则执行复制操作。考虑到 RVO,将 std::move 添加到 return 类型是没有价值的,因此值 returned 不会被复制而是被移动。然而,两个示例中的赋值应该做同样的事情:将 returned 向量(右侧)的地址分配给左侧的向量。

问题:根据我的理解(可能是错误的)并考虑到这两个例子,为什么[=39=之间的执行时间差异如此之大? ]Example1 和 Example2 如果两者执行相同的操作(优化已激活)。我可以做些什么来减少第二个例子的时间吗? (我想让第二个例子尽可能高效)

谢谢。

这不是一个答案,它是一种尝试理解时间差异的方法,但这太长了,无法作为备注给出

在第一种情况下,您总是在内存中重复使用相同的块,执行期间所需的大小很小

但是在第二个解决方案中你需要多 128 倍的内存,这可能解释了时间的差异吗?如果执行时间是实时的(执行期间交换?)

案例比较:

int main(int, char ** argv)
{
  switch (*argv[1]) {
  case '1':
    {
      // this is your first case
      std::vector<float> data;
      for (int i = 1; i <= 128; ++i) {
        data = read_file(getFile(i));
      }
    }
    break;
  case '2':
    {
      // this is your seconde case
      std::vector<std::vector<float>> data(128);
      for (auto i = 1; i <= 128; ++i) {
        data[i-1] = read_file(getFile(i));
      }
    }
    break;
  default:
    {
      // this is equivalent to your first case EXCEPT that needs 128 times more memory 
      std::vector<std::vector<float> *> data(128);
      for (auto i = 1; i <= 128; ++i) {
        data[i-1] = new std::vector<float>();
        *(data[i-1]) = read_file(getFile(i));
      }
    }
    break;
  }

  return 0;
}

当您 运行 使用参数 3 时,您会得到参数为 1 或 2 的时间吗?如果 2 和 3 相似,则表示原因是需要更大的内存大小。

我发现的问题是 I/O 性能低下的 WSL 环境(我正在使用 CLion 进行编译)。尽管我在问题中没有提到这方面,但我不得不在各种平台和系统上编译相同的程序,以便了解到底发生了什么。

设置另一个构建环境解决了这个问题(示例 1 和 2 的执行时间现在也非常相似)