C++ 选择性能最好的容器(阵列)

C++ 选择性能最好的容器(阵列),c++,C++,这是我关于容器的一个大问题,特别是数组 我正在写一个物理代码,主要操作一大组(>1000000)的“粒子”(每个粒子有6个double坐标)。我正在寻找实现一个类的最佳方法(就性能而言),该类将包含这些数据的容器,并为这些数据提供操作原语(例如实例化、operator[]等) 如何使用此集合有一些限制: 它的大小是从配置文件读取的,在执行期间不会更改 可以将其视为一个由N(例如1000 000)行和6列(每个列存储一维坐标)组成的大二维数组 数组在一个大循环中操作,访问每个“粒子/线”,并使用

这是我关于容器的一个大问题,特别是数组

我正在写一个物理代码,主要操作一大组(>1000000)的“粒子”(每个粒子有6个
double
坐标)。我正在寻找实现一个类的最佳方法(就性能而言),该类将包含这些数据的容器,并为这些数据提供操作原语(例如实例化、
operator[]
等)

如何使用此集合有一些限制:

  • 它的大小是从配置文件读取的,在执行期间不会更改
  • 可以将其视为一个由N(例如1000 000)行和6列(每个列存储一维坐标)组成的大二维数组
  • 数组在一个大循环中操作,访问每个“粒子/线”,并使用其坐标进行计算,然后将结果存储回该粒子,依此类推每个粒子,依此类推大循环的每次迭代
  • 在执行过程中不会添加或删除新元素
第一个结论,由于对元素的访问基本上是通过使用
[]
逐个访问每个元素来完成的,因此我认为应该使用普通的动态数组

我已经探索了一些东西,我想听听你对能给我最好表现的那个的看法

据我所知,使用动态分配的数组而不是
std::vector
,没有任何优势,因此排除了
double**array2d=new…、new循环等情况

那么使用
std::vector
是一个好主意吗

如果我使用一个
std::vector
,我应该创建一个像
std::vector my_array
那样可以像
my_array[I][j]
那样索引的二维数组,还是一个坏主意,最好使用
std::vector other_array
并使用
other_array[6*I+j]

也许这可以提供更好的性能,特别是当列的数量是固定的并且从一开始就知道时

如果您认为这是最好的选择,那么是否可以将此向量包装成一种可以使用定义为
other_array[i,j]//与other_array[6*i+j]
的索引运算符访问的方式,而无需开销(如每次访问时的函数调用)

另一个选项,我目前使用的是Blitz,特别是
Blitz::Array

typedef blitz::Array<double,TWO_DIMENSIONS> store_t;
store_t my_store;
typedef闪电战::数组存储\u t;
存储我的存储;
我的元素是这样访问的:
myu存储(行、列)

我认为在我的例子中使用Blitz没有什么好处,因为我一个接一个地访问每个元素,如果我直接在数组上使用操作(比如矩阵乘法),Blitz会很有趣,而我不是

你认为闪电战可以吗,还是对我没用

到目前为止,这些都是我考虑过的可能性,但也许是最好的一个,我还是另一个,所以请不要犹豫,给我提出其他建议

非常感谢你在这个问题上的帮助

编辑:

从下面非常有趣的答案和评论来看,一个好的解决方案似乎是:

  • 使用结构<代码>粒子
(包含6个双精度)或6个双精度的静态数组(避免使用二维动态数组)
  • 使用此
    粒子
    结构或数组的
    向量
    deque
    。然后最好使用迭代器遍历它们,这将允许以后从一个迭代器更改到另一个迭代器

  • 此外,我还可以使用一个
    Blitz::TinyVector
    而不是一个结构。

    首先,您不想将一个给定粒子的坐标分散到所有地方,因此我将首先编写一个简单的
    结构

    struct Particle { /* coords */ };
    
    然后我们可以把这些
    粒子
    做成一个简单的一维数组

    我可能会使用一个
    deque
    ,因为这是默认的容器,但您可能希望尝试一个
    vector
    ,它只是1.000.000个粒子意味着大约几兆字节的单个块。它应该可以保持,但如果它增长,可能会使系统紧张,而
    deque
    将分配几个块

    警告

    正如Alexandre C所说,如果你走
    deque
    之路,不要使用
    操作符[]
    ,而是更喜欢使用迭代风格。如果您确实需要随机访问,而且它对性能非常敏感,那么
    向量应该更快

    那么使用
    std::vector
    是一个好主意吗

    通常,容器的首选应该是
    std::vector
    。您可以使用
    std::vector::reserve()
    std::vector::resize()
    来避免在填充向量时重新分配。通过测量可以发现是否有其他容器更好。只有通过测量。但首先要衡量容器涉及的任何内容(填充、访问元素)是否值得优化

    如果我使用std::vector,我应该创建一个像
    std::vector
    […]这样的二维数组吗

    不,IIUC,您访问的是每个粒子的数据,而不是每行的数据。如果是这样,为什么不使用
    std::vector
    ,其中
    particle
    是一个包含六个值的结构?即使我理解错误,你也应该在一维容器周围写一个二维包装。然后以行或列的形式对齐数据—使用访问模式会更快

    你认为闪电战可以吗,还是对我没用

    我对blitz++及其使用领域没有实际知识。但是blitz++不是全部都是关于表达式模板来展开循环操作和优化临时操作吗
    other_array[i][j]
    other_array(i, j)  // if other_array implements operator()(int, int),
                       // but std::vector<> et al don't.
    other_array[i].identifier // identifier is a member variable
    other_array[i].identifier() // member function getting value
    other_array[i].identifier(double) // member function setting value
    
    struct Particle
    {
        double x[6];
        double& speed() { return x[3]; }
        double speed() const { return x[3]; }
        double& acceleration() { return x[5]; }
        ...
    };