C++分配N维向量而不复制C数组

3

我希望能够将磁盘(HDF5)中的N维矩阵加载到std::vector对象中。

我预先知道它们的秩,但不知道形状。例如,其中一个矩阵是4级 std::vector<std::vector<std::vector<std::vector<float>>>> data;

我想使用向量来存储值,因为它们是标准的,并且不像c数组那么难看(主要是因为它们知道它们的长度)。

然而,加载它们的方式是使用一个加载函数,该函数接受void *,这对于秩为1的向量可以正常工作,我可以调整它们的大小,然后访问它的数据指针(vector.data())。 对于更高的秩,vector.data()只会指向vector,而不是实际的数据。

最坏的情况是我将所有数据加载到辅助c数组中,然后手动复制它们,但对于大型矩阵,这可能会使速度变慢。

有没有一种方法可以在向量中拥有连续的多维数据,然后获得单个地址?


你似乎需要一个更好的库来实现你的目的,我建议使用Eigen - bracco23
3
我建议将矩阵存储在一个扁平的std::vector<float>中,并封装它在一个类中以伪造它有多个维度。这样可以调用向量上的data来获取指向整个矩阵数据的指针(连续的)。否则,您基本上拥有一个float****,每个*可能在内存中的任何位置(不连续)。 - NathanOliver
3个回答

5

如果您关心性能,请不要使用向量的向量的向量...

这里是原因。我认为@OldPeculier的答案值得一读。

它既臃肿又缓慢的原因实际上是相同的。矩阵中的每一行都是单独分配的动态数组。进行堆分配既费时间又费空间。分配器需要花费时间来进行分配,有时运行O(n)算法来执行此操作。分配器还会使用额外的字节进行填充和对齐以管理您的行数组。这些额外的空间成本很高。当您开始释放矩阵时,解除分配器将花费额外的时间,费力地释放每个单独的行分配。仅想想就让我出汗了。
它缓慢的另一个原因是这些单独的分配 tend to live in discontinuous parts of memory. 一行可能在地址1,000处,另一行可能在地址100,000处——你明白了吧。这意味着当您遍历矩阵时,就像一个疯狂的人一样跳跃到内存中。这往往会导致缓存未命中,从而大大减慢处理时间。
因此,如果您绝对必须使用可爱的[x] [y]索引语法,请使用该解决方案。如果您想要快速且小巧(如果您不关心这些,为什么要使用C ++?),则需要使用其他解决方案。

3
你的计划并不明智。向量的向量的向量效率低下,只有在动态锯齿数组中才真正有用,而你没有这个需求。
相反,应该加载到一个 flst 向量中。
接下来,使用多维视图进行包装。
template<class T, size_t Dim>
struct dimensional{
  size_t const* strides;
  T* data;
  dimensional<T, Dim-1> operator[](size_t i)const{
     return {strides+1, data+i* *strides};
  }
};
template<class T>
struct dimensional<T,0>{
  size_t const* strides; // not valid to dereference
  T* data;
  T& operator[](size_t i)const{
     return data[i];
  }
};

strides指向每个维度的数组步幅(所有后面维度大小的乘积)的数组。

因此,my_data.access()[3][5][2]获取特定元素。

这个解决方案的草图将所有内容公开,并且不支持for(:)迭代。更高质量的解决方案将具有适当的隐私和支持风格的循环。

我不知道是否已经为您编写了高质量的多维数组视图的名称,但几乎肯定在boost中存在一个。


0

对于一个二维矩阵,你可以使用一个丑陋的C数组,如下:

float data[w * h]; //width, height
data[(y * w) + x] = 0; //access (x,y) element

对于一个三维矩阵:

float data[w * h * d]; //width, height, depth
data[((z * h) + y) * w + x] = 0; //access (x,y,z) element

等等。要从文件中加载数据,

float *data = yourProcToLoadData(); //works for any dimension

这不是非常可扩展的,但你可以处理已知的维度。这样,你的数据是连续的,并且有一个单一的地址。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接