c++ - 使用向量在 C++ 中声明 3D 数组结构
问题描述
嗨,我是一名使用 C++ 学习科学计算的研究生。我们的一些研究集中在算法的速度上,因此构造足够快的数组结构很重要。
我见过两种构造 3D 数组的方法。第一个是使用矢量库。
vector<vector<vector<double>>> a (isize,vector<double>(jsize,vector<double>(ksize,0)))
这给出了大小为 isize x jsize x ksize 的 3D 数组结构。
另一种是构造一个包含大小为 isize* jsize * ksize 的一维数组的结构,使用
new double[isize*jsize*ksize]
. 要轻松访问 (i,j,k) 的特定位置,需要运算符重载(对吗?)。
根据我的经验,第一个要快得多,因为它可以轻松访问位置 (i,j,k),而后一个必须计算位置并返回值。但是我看到有些人更喜欢后一种而不是第一种。为什么他们更喜欢后一种设置?使用第一个有什么缺点吗?
提前致谢。
解决方案
它们之间的主要区别在于布局:
vector<vector<vector<T>>>
这将为您提供一维数组vector<vector<T>>
。
每个项目将是一维数组vector<T>
。
并且这些一维数组中的每一项都是 T 的一维数组。
关键是,vector
它本身不存储其内容。它管理一块内存,并将内容存储在那里。这会带来许多不好的后果:
- 对于维度 X·Y·Z 的矩阵,您最终将分配
1 + X + X·Y
内存块。这非常慢,并且会破坏堆。想象一下:一个大小为 20 的立方体矩阵会触发 421 次调用new
! - 要访问一个单元格,您有 3 个间接级别:
- 您必须访问该
vector<vector<vector<T>>>
对象以获取指向顶级内存块的指针。 - 然后,您必须访问该
vector<vector<T>>
对象以获取指向二级内存块的指针。 - 然后,您必须访问该
vector<T>
对象以获取指向叶子内存块的指针。 - 只有这样您才能访问
T
数据。
- 您必须访问该
- 这些内存块将分布在堆周围,导致大量缓存未命中并减慢整体计算速度。
- 如果您在某些时候弄错了,可能会导致矩阵中的某些行具有不同的长度。毕竟,它们是独立的一维数组。
new T[X * Y * Z]
另一方面,拥有一个连续的内存块(如)给出:
- 您分配 1 个内存块。没有堆垃圾,O(1)。
- 您只需要访问指向内存块的指针,然后就可以直接获取所需的元素。
- 所有矩阵在内存中都是连续的,这是缓存友好的。
在那些日子里,单个缓存未命中意味着数十或数百个计算周期丢失,不要低估缓存友好性方面。
顺便说一句,您可能没有提到一种更好的方法:使用众多矩阵库之一,它会自动为您处理这个问题并提供很好的支持工具(如 SSE 加速矩阵运算)。一个这样的库是Eigen,但还有很多其他的。
→ 你想做科学计算?让一个库处理样板和基础知识,这样您就可以专注于科学计算部分。
推荐阅读
- angular - Angular 类没有实现继承的抽象成员
- python - 如何在 docker 中仅发送通知请求
- python - 显示第一年并每年递增
- java - 在更新表之前使用Java检查确定mySQL表中是否有数据
- html - 如何使页面上的像素显示为整数?(铬合金)
- asp.net-core - 用户身份角色
- file-upload - Fetch API 将损坏的 Excel 文件上传到 Dropbox
- javascript - 使用 Javascript 的动画 SVG 徽标
- python - python中出现错误时如何运行函数
- hibernate - 我可以在调用返回结果集但也更新行的存储过程的方法上使用@Transactional(readOnly = true) 吗?