我想将N维矩阵从磁盘(HDF5)加载到std::vector
对象中。
我事先知道他们的等级,只是不知道形状。例如,矩阵之一是4级std::vector<std::vector<std::vector<std::vector<float>>>> data;
我想使用向量来存储值,因为它们是标准的,并且不如c数组丑陋(主要是因为它们知道它们的长度)。
但是,加载它们的方式是使用带有void *
的加载函数,该函数对于等级1的向量很好用,在这里我可以调整它们的大小然后访问其数据指针(vector.data()
)。对于较高的排名,vector.data()
只会指向vector
,而不是实际数据。
在最坏的情况下,我只是将所有数据加载到辅助c数组中,然后手动复制它,但这对于大型矩阵可能会使其速度大大降低。
是否有一种方法可以在向量中包含连续的多维数据,然后为其获取一个地址?
答案 0 :(得分:5)
如果您担心性能,请不要使用vector ...的vector。
Here是为什么。我认为@OldPeculier的答案值得一读。
它既胖又慢的原因实际上是相同的。矩阵中的每个“行”都是一个单独分配的动态数组。进行堆分配在时间和空间上都是昂贵的。分配器需要一些时间来进行分配,有时需要运行O(n)算法来进行分配。分配器会用额外的字节“填充”每个行数组以进行簿记和对齐。多余的空间要花……好……多余的空间。当您去分配矩阵时,释放分配器也将花费额外的时间,并辛苦地释放每个单独的行分配。想起来让我大汗淋漓。
还有一个慢的原因。这些单独的分配往往存在于内存的不连续部分中。一行可能位于地址1,000,另一行可能位于地址100,000,您就会明白。这意味着当您遍历矩阵时,您像野人一样在内存中跳跃。这往往会导致高速缓存未命中,从而大大降低您的处理时间。
因此,如果绝对必须具有可爱的[x] [y]索引语法,请使用该解决方案。如果您想要敏捷和小巧(如果您不关心这些,为什么要使用C ++?),您需要一个不同的解决方案。
答案 1 :(得分:3)
您的计划不是明智的。向量的向量效率低下,仅对动态锯齿阵列有用,而实际上没有。
而不是您的计划,而是加载到第一个向量中。
接下来,用多维视图包装它。
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(:)
迭代。更高的运输质量将具有适当的隐私权,并支持c++11样式的循环。
我不知道已经为您编写的高质量多维数组视图的名称,但是几乎可以肯定其中的一个。
答案 2 :(得分:0)
对于二维矩阵,您可以使用像这样的丑陋c数组:
<DataGridTextColumn.CellStyle>
<Style TargetType="{x:Type DataGridCell}" BasedOn="{StaticResource {x:Type DataGridCell}}">
<Setter Property="ToolTip">
<Setter.Value>
<ToolTip>
<TextBlock Text="{Binding PlacementTarget.Content.Text,
RelativeSource={RelativeSource AncestorType=ToolTip}}" />
</ToolTip>
</Setter.Value>
</Setter>
</Style>
</DataGridTextColumn.CellStyle>
对于三维矩阵:
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
这不是很可扩展,但是您要处理一个已知尺寸。这样,您的数据是连续的,并且您只有一个地址。