这是关于容器的一个小问题,特别是数组.
我正在编写一个物理代码,主要操作一个大的(> 1 000 000)"粒子"集(double每个有6个坐标).我正在寻找最好的方法(在性能方面)来实现一个类,该类将包含这些数据的容器,并将为这些数据提供操作原语(例如实例化operator[]等).
如何使用此集合有一些限制:
第一个结论,因为对元素的访问基本上是通过逐个访问每个元素来完成的[],我认为我应该使用普通的动态数组.
我已经探讨了一些事情,我想对那些可以给我最好表现的人发表意见.
据我所知,使用动态分配的数组而不是a是没有优势的std::vector,因此double** array2d = new ..., loop of new, etc排除了类似的东西.
那么使用它是个好主意std::vector<double>吗?
如果我使用a std::vector,我应该创建一个像std::vector<std::vector<double> > my_array索引一样的二维数组my_array[i][j],或者这是一个坏主意,最好使用std::vector<double> other_array和访问它other_array[6*i+j].
也许这可以提供更好的性能,特别是当列的数量是固定的并且从一开始就知道.
如果您认为这是最佳选择,是否可以将这个向量包装为可以使用定义为other_array[i,j] // same as other_array[6*i+j]没有开销的索引运算符(如每次访问时的函数调用)访问它?
另一种选择,我到目前为止使用的是使用闪电战,特别是blitz::Array:
typedef blitz::Array<double,TWO_DIMENSIONS> store_t;
store_t my_store;
Run Code Online (Sandbox Code Playgroud)
我的元素被访问的地方:my_store(line, column);.
我认为在我的情况下使用Blitz没有多大优势,因为我逐个访问每个元素,如果我直接在数组上使用操作(如矩阵乘法),那么Blitz会很有趣,我不是.
你认为闪电战是好的,还是我的情况没用?
这些是我到目前为止考虑的可能性,但也许是最好的一个我还是另一个,所以不要犹豫,建议我其他的东西.
非常感谢您对此问题的帮助!
编辑:
从非常有趣的答案和评论下面看来,一个好的解决方案如下:
particle(包含6个双打)或6个双打的静态数组(这避免使用二维动态数组)vector或一个deque这种particle结构或数组.然后用迭代器遍历它们是很好的,这将允许稍后从一个变为另一个.另外我也可以使用a Blitz::TinyVector<double,6>而不是结构.
那么使用它是个好主意
std::vector<double>吗?
通常,a std::vector应该是容器的首选.你可以使用两种std::vector<>::reserve()或std::vector<>::resize()避免再分配在填充载体.是否可以通过测量找到任何其他容器更好.而且只能通过测量.但首先要衡量容器是否涉及(填充,访问元素)是否值得优化.
如果我使用std :: vector,我应该创建像
std::vector<std::vector<double> >[...] 这样的二维数组吗?
编号IIUC,您每个粒子访问您的数据,而不是每行.如果是这种情况,为什么不使用a std::vector<particle>,哪里particle是一个包含六个值的结构?即使我理解不正确,你也应该在一维容器周围写一个二维包装器.然后按行或列对齐数据 - 访问模式的速度更快.
你认为闪电战是好的,还是我的情况没用?
我没有关于blitz ++及其所用区域的实用知识.但是不是blitz ++所有关于表达式模板来展开循环操作并在进行矩阵操作时优化临时工作?ICBWT.
首先,您不想将一个给定粒子的坐标分散到各处,因此我首先编写一个简单的struct:
struct Particle { /* coords */ };
Run Code Online (Sandbox Code Playgroud)
然后我们可以制作一个简单的一维数组Particles。
我可能会使用 a deque,因为这是默认容器,但您可能希望尝试 a vector,只是 1.000.000 个粒子意味着大约几 MB 的单个块。它应该保持不变,但如果它增长,它可能会给您的系统带来压力,同时deque会分配几个块。
警告:
正如 Alexandre C 所说,如果你走这deque条路,就不要使用operator[]迭代风格,而更喜欢使用迭代风格。如果您确实需要随机访问并且对性能敏感,那么vector应该会更快。