C++ 初始化 3D 矢量的最有效方法是什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18062463/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 21:41:39  来源:igfitidea点击:

What is the most efficient way to initialize a 3D vector?

c++performancevector

提问by ChangeMyName

I have a 3D string vector in C++:

我在 C++ 中有一个 3D 字符串向量:

vector<vector<vector<string>>> some_vector

That I am trying is to find a fast method to allocate memory for it.

我正在尝试的是找到一种为其分配内存的快速方法。

I tried to define it with two different methods as follow:

我尝试用以下两种不同的方法定义它:

#include<vector>
#include<iostream>
#include<ctime>
using namespace std;

#define DIM1 100
#define DIM2 9
#define DIM3 120

int main()
{
    clock_t t1_start = clock();
    vector<vector<vector<string>>> vec1(DIM1, vector<vector<string>>(DIM2, vector<string>(DIM3)));
    clock_t t1_end = clock();
    double diff1 = (t1_end - t1_start) / double(CLOCKS_PER_SEC);

    clock_t t2_start = clock();
    vector<vector<vector<string>>> vec2;
    vec2.resize(DIM1);
    for(int i = 0; i < DIM1; i++)
    {
        vec2[i].resize(DIM2);
        for(int j = 0; j < DIM2; j++)
            vec2[i][j].resize(DIM3);
    }
    clock_t t2_end = clock();

    double diff2 = (t2_end - t2_start) / double(CLOCKS_PER_SEC);

    cout<<"1st definition used time: "<<diff1<<"s"<<endl;
    cout<<"2nd definition used time: "<<diff2<<"s"<<endl;
}

I expect that the first method (vec1) could be faster than the 2nd one (vec2).

我希望第一种方法 (vec1) 可能比第二种方法 (vec2) 快。

But it turned out that the 1st method is much slower than the 2nd. On my machine, the 1st method used 0.245 seconds, while the 2nd method used 0.152 seconds.

但事实证明,第一种方法比第二种方法慢得多。在我的机器上,第一种方法使用了 0.245 秒,而第二种方法使用了 0.152 秒。

Moreover, when I switch the data type to int, the 1st one took 0.058 second, and the 2nd took 0.004.

此外,当我将数据类型切换为 int 时,第一个需要 0.058 秒,第二个需要 0.004。

May I know what cause such difference? And is there better way to allocate memory for a 3D vector?

我可以知道是什么导致了这种差异吗?有没有更好的方法来为 3D 矢量分配内存?

Many thanks in advance.

提前谢谢了。

回答by Mike Seymour

May I know what cause such difference?

我可以知道是什么导致了这种差异吗?

The first version constructs a 2-d vector by copying a 1-d vector, and then constructs the 3-d vector by copying that. This might be slower than resizing the vectors without copying. However, I'd hope that the difference would be negligible if you're building with optimisation.

第一个版本通过复制 1-d 向量构造一个 2-d 向量,然后通过复制它来构造 3-d 向量。这可能比在不复制的情况下调整向量的大小要慢。但是,如果您使用优化进行构建,我希望差异可以忽略不计。

And is there better way to allocate memory for a 3D vector?

有没有更好的方法来为 3D 矢量分配内存?

It might be better to use a single contiguous array, wrapped in a class that provides multi-dimensional accessors. This would make allocation much simpler, and would also avoid some pointer dereferencing when accessing elements (at the cost of a bit of arithmetic). Something like this:

最好使用单个连续数组,封装在提供多维访问器的类中。这将使分配更简单,并且还可以避免访问元素时的一些指针取消引用(以一些算术为代价)。像这样的东西:

template <typename T>
class vector3d {
public:
    vector3d(size_t d1=0, size_t d2=0, size_t d3=0, T const & t=T()) :
        d1(d1), d2(d2), d3(d3), data(d1*d2*d3, t)
    {}

    T & operator()(size_t i, size_t j, size_t k) {
        return data[i*d2*d3 + j*d3 + k];
    }

    T const & operator()(size_t i, size_t j, size_t k) const {
        return data[i*d2*d3 + j*d3 + k];
    }

private:
    size_t d1,d2,d3;
    std::vector<T> data;
};

回答by Jerry Coffin

I think I'd optimize it by allocating one large block of memory instead of a lot of little ones. This one is only 2D instead of 3D, but gives the basic idea:

我想我会通过分配一大块内存而不是很多小内存来优化它。这只是 2D 而不是 3D,但给出了基本思想:

template <class T>
class matrix { 
    size_t columns_;
    std::vector<T> data;
public:
    matrix(size_t columns, size_t rows) : columns_(columns), data(columns*rows) {}

    T &operator()(size_t column, size_t row) { return data[row*columns_+column]; }
};

For 3D, you'll need to deal with "planes" (or something) along with rows and columns, but the basic idea is pretty much the same.

对于 3D,您需要处理“平面”(或其他东西)以及行和列,但基本思想几乎相同。

回答by fb77

To initialize a 3D string vector you shall initialize the vector structure for each dimension one at a time and for each index, for instance:

要初始化 3D 字符串向量,您应该一次为每个维度和每个索引初始化向量结构,例如:

  vector<vector<vector<string> > > myvector; //declare the 3D vector
  for(k=0; k<3; k++)
  {
    myvector.push_back(vector<vector<string> >()); //initialize the first index with a 2D vector
    for(i=0; i<4; i++)
    {
      myvector[k].push_back(vector<string>()); //initialize the 2 index with a row of strings
      for(j=0; j<4; j++)
      {
         result = " whatever you want to insert in the vector element";
         myvector[k][i].push_back(result); //fulfill the last index regularly
      } 
    }
  }

回答by Neil Kirk

When you initialize a vector of vectors in the first method, a temporary vector is allocated and then copied into the outer vector the required number of times. This means you have an extra allocation that is unnecessary and the new elements are initialized by copying their value from another data structure, which uses more memory accesses.

在第一种方法中初始化向量向量时,会分配一个临时向量,然后将所需次数复制到外部向量中。这意味着你有一个额外的分配是不必要的,新元素是通过从另一个数据结构复制它们的值来初始化的,这会使用更多的内存访问。

Resizing the vectors as per the second method is more ugly but avoids the extra allocation. Furthermore the new elements are created by the default constructor and do not need to copy from other vectors. This will also be faster.

按照第二种方法调整向量的大小更难看,但避免了额外的分配。此外,新元素由默认构造函数创建,不需要从其他向量复制。这也会更快。

If speed matters (and maybe it doesn't, premature optimization and all that), then you must use the second method (OR a single-block allocation as suggested by the other answers). I don't have faith that a compiler can simply "optimize" away the inefficiency of the first method.

如果速度很重要(也许它不重要,过早优化等等),那么您必须使用第二种方法(或其他答案建议的单块分配)。我不相信编译器可以简单地“优化”第一种方法的低效率。