【问题标题】:Multidimension vector concept C++多维向量概念 C++
【发布时间】:2014-09-18 13:04:22
【问题描述】:

我有一个巨大的 3d 矢量,用于存储双精度值。为了提高性能,我想在处理之前提前保留我知道的元素数量;但是,我无法真正弄清楚在这种情况下,reserve&clear&erase 是如何工作的。

我已经实现了一个在这种情况下具有二维向量的小程序,请参见下面的代码 sn-p:`

for(int counter = 0; counter < 2; counter++){
    cout << "Counter-> " << counter << endl;

    vector<vector<double> > vec2D;
    vec2D.reserve(2);

    // assign values to the vec
    for(int i = 0; i < 2; i++){
        vec2D[i].reserve(5);
        for(int j = 0; j < 5; j++){
            vec2D[i][j] = j;
        }
    }

    // print the vector content
    for(int i = 0; i < 2; i++){
        for(int j = 0; j < 5; j++){
            cout << vec2D[i][j] << "\t";
        }
        vec2D[i].clear();
        cout << endl;
    }
    vec2D.clear();
}

当我运行这段代码 sn-p 时,它只遍历 for 循环一次,而它应该执行两次;但是,当我在 for 循环之外声明向量时,它会迭代两次。上面sn -p的输出是:

Counter-> 0
0   1   2   3   4   
0   1   2   3   4   
Counter-> 1

您能否说明一下在这种情况下它实际上应该如何以及它是如何工作的。

提前致谢。

【问题讨论】:

标签: c++ memory-management vector multidimensional-array


【解决方案1】:

你的代码有一个大问题:reserve() 不会改变向量的大小,只会改变它的存储容量(以避免将来发生系统调用)。

你的情况需要reserve()而不是assign()resize()

【讨论】:

  • 感谢您的回答。在当前的工作代码中,我正在使用调整大小。看起来像这样:vector > vec(5, vector(8));然后为这个向量分配一些值(在实际情况下,它是一个 3d 向量,尺寸为 100kX5X8。为了提高性能,我开始使用保留方法。
【解决方案2】:

如果您想要任何类似的性能,请不要使用向量向量:这是非常低效的。这可能是最有效的内存利用率,并且比向量更快的访问,尽管有一些内存权衡更快的解决方案:

class GridWithSmallDimensions
{
    double * values;
    int sizeX, sizeY, sizeZ;
public:
    GridWithSmallDimensions(int x, int y, int z) 
    : sizeX(x), sizeY(y), sizeZ(z)
    {
        values = new double [x*y*z];
    }
    ~ GridWithSmallDimensions()
    {
        delete [] values;
    }
    double get(int x, int y, int z)
    {
        return value[x+sizeX*(y+sizeY*z)];
    }
    void set(int x, int y, int z, double v)
    {
        value[x+sizeX*(y+sizeY)] = v;
    }
};

这是一个稍微复杂的实现,旨在减少索引计算:

class GridWithRowPointers
{
    int sizeX, sizeY, sizeZ; // Dimensions
    double * values; // Data
    double ** rows; // Pointers to "rows" of data indexed by x

    inline int getIndex(y, z) const // Get index of data within a row
    {
        return sizeZ * y + z;
    }

public:
    GridWithRowPointers(int x, int y, int z) 
    : sizeX(x), sizeY(y), sizeZ(z)
    {
        values = new double [x*y*z]; // Allocate data
        rows = new (double*) [x]; // Allocate row pointers
        for( int n = 0; n < sizeX; n++ )
        {
            rows[n] = values + sizeY * sizeZ;
        }
    }

    ~ GridWithRowPointers()
    {
        delete [] values;
        delete [] rows;
    }

    inline double get(int x, int y, int z) const
    {
        // Access value via row pointer
        return rows[ x ][ getIndex(y,z) ];
    }

    inline void set(int x, int y, int z, double v)
    {
        // Access value via row pointer
        rows[ x ][ getIndex(y,z) ] = v;
    }
};

【讨论】:

  • 这真是一种聪明的做法。真的很喜欢。非常感谢!只需将我的代码中的 2 个向量结构更改为这种结构,性能就会提高 %8。
  • 通过打开 -pg 标志使用 GNU 编译器分析我的代码,我可以看到大部分时间都花在了 GridWithSmallDimensions 类的 get 方法上。是因为指数的计算吗?有没有办法最小化这个?我对存储在这些向量中的值进行了大量计算,因为每个向量可能包含数千个元素。假设我的程序总共需要 2 分钟,其中 26 秒用于 get() 方法。附言在我的情况下,该方法给了我 %25 的内存优化。就我而言,内存使用与速度一样重要。谢谢。
  • @serhatg:两个 cmets。首先,可能涉及缓存局部性。这意味着时间被浪费了,因为值的访问不是按照它们分配的顺序。例如,如果您有 for(x=...) for(y=...) for(z=...) { do something } 类型的循环,您希望以这种方式索引到值数组中,以便x 和 y 相同但 z 略有不同的值彼此靠近存储。这只是一种索引方式,x+sizeX*(y+sizeYz) 与 z+sizeZ*(y+sizeYx)。其次,一种流行的技术是预先分配指向数据“行”的指针以节省乘法,正如我刚刚添加的那样。
  • 非常感谢@Michael 的建议
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多