在c++中处理大矩阵
Handling large matrices in C++
我在c++中使用double
s的大矩阵。我需要从这些矩阵中得到行或列并把它们传递给一个函数。我最快的方法是什么?
- 一种方法是编写一个函数,返回所需行或列的副本作为
- 另一种方法是将整个东西作为引用传递,并修改函数以能够读取所需值。
std::vector
。还有其他选择吗?你推荐哪一种?
顺便说一句,你建议我如何在矩阵类中存储数据?我现在正在使用std::vector< std::vector< double > >
。
编辑
我必须提到矩阵可能有两个以上的维度。因此,在这里使用boost或arma::mat
是不可能的。虽然,我在库的其他部分使用armadillo
如果关键需求是2以上的可变维数,请查看boost的多维数组库。它具有高效(无复制)"视图"可以用来引用完整矩阵的低维"切片"。
对于这类事情,什么是"最快"的细节在很大程度上取决于你到底在做什么,以及访问模式/工作集"足迹"如何适合你的HW的各种缓存和内存延迟级别;在实践中,复制到更紧凑的表示来获得更多的缓存一致性访问是值得的,而不是进行稀疏的跨行访问,因为这只会浪费大量的缓存线。替代方案是Morton-order访问方案,它至少可以在所有轴上摊销"坏轴"效应。只有你自己对自己的代码和用例进行基准测试才能真正回答这个问题。(注意,我不会使用Boost。用于二维数组的MultiArray -对于线性代数/图像处理应用程序有更快,更好的选择-但对于3+,值得考虑
我会使用像http://arma.sourceforge.net/这样的库,因为您不仅可以获得存储矩阵的方法。您还可以使用函数对其进行操作。
高效(多)线性代数是一门非常深奥的学科;没有简单的放之四海而皆准的答案。主要的挑战是数据局部性:计算机的内存硬件是为访问连续的内存区域而优化的,并且可能一次只能在缓存线上操作(即使可以,效率也会下降)。
缓存行的大小不同,但考虑64或128字节。
正因为如此,将数据放在矩阵中以使其可以在多个方向上有效地访问是一个非平凡的挑战;对于高阶张量更是如此。
此外,最好的选择可能在很大程度上取决于你对矩阵做了什么。
你的问题真的不是一个可以用这样的形式令人满意地回答的问题。
但为了至少让你开始研究,这里有两个关键短语可能值得研究:
- <
- 块矩阵/gh> 快速转置算法
你最好使用一个库,而不是自己编写;例如闪电战+ +。(免责声明:我没有使用blitz++)
vector<vector<...>>
分配的速度很慢,释放的速度很慢,访问的速度也很慢,因为它会有多个解引用(不是缓存友好的)。
只有当你的(行或列)没有相同的大小(锯齿数组)时,我才会推荐它。
对于一个"正常"矩阵,你可以这样写:
template <class T, size_t nDim> struct tensor {
size_t dims[nDim];
vector<T> vect;
};
和重载operator(size_t i, size_t j, etc.)
来访问元素
operator()
必须进行索引计算(您必须在以行为主的顺序或以列为主的顺序之间进行选择)。对于nDim > 2
,它变得有些复杂,并且可以从缓存一些索引计算中获益。
若要返回行或列,则可以定义子类型。
template <class T, size_t nDim> struct row /*or column*/ {
tensor<T, nDim> & tensor;
size_t iStart;
size_t stride;
}
然后定义一个将返回tensor.vect[iStart + i*stride]
的operator(size_t i)
stride
值将取决于它是行还是列,以及(行为主还是列为主)排序选择。
stride
对于子类型之一将为1。注意,对于这个子类型,迭代可能会快得多,因为它是缓存友好的。不幸的是,对于其他子类型,它可能会相当慢,并且您对此无能为力。
请参阅其他关于为什么先迭代行后迭代列可能会比先迭代列后迭代行有巨大性能差异的问题。
我建议您通过引用传递它,因为根据大小的不同,复制可能是一个缓慢的过程。如果您希望能够扩展和收缩容器,Std::vector是可以的。
- 警告处理为错误这里有什么问题
- 在C#中处理C++指针而不使用unsafe的最佳方法
- 处理多个异常集合的C++方法
- 找不到成员对象:没有名为get_event()的成员,也处理多态性和向量
- 使用流处理接收到的数据
- 获取日期异步信号安全吗?如果在信号处理程序中使用,它会导致死锁吗
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- 基于多个条件处理地图中的所有元素
- 如何用数字处理log(0)
- SSL上的`curl_easy_send`和`curl_asy_recv`:如何处理`CURLE_AGAIN`
- 错误处理.将系统错误代码映射到泛型
- 从文本文件中读取时钟时间和事件时间并进行处理
- 在运行时处理类型擦除的数据-如何不重新发明轮子
- 在for循环中使用auto vs decltype(vec.size())来处理字符串的向量
- 用于矢量处理的多个线程
- 对字符串进行排序时,在c++中处理sort()
- 如何处理linux终端中带有负号(-)的C++中的命令行参数
- 处理除以零会导致<csignal>意外行为
- 是否可以在c++中处理字符串流中的各个元素
- 在多个核心中处理一个HTTP请求