【问题标题】:std::sort on container of pointersstd::sort 在指针容器上
【发布时间】:2012-03-11 19:08:50
【问题描述】:

我想探索在新分配的结构(或类)向量内多次取消引用数据的性能差异。

struct Foo
{
    int val;
    // some variables
}

std::vector<Foo*> vectorOfFoo;

// Foo objects are new-ed and pushed in vectorOfFoo
for (int i=0; i<N; i++)
{
   Foo *f = new Foo;
   vectorOfFoo.push_back(f);
}

在我迭代向量的代码部分中,我想通过许多迭代器取消引用来增强引用的局部性,例如我经常执行双嵌套循环

for (vector<Foo*>::iterator iter1 = vectorOfFoo.begin(); iter!=vectorOfFoo.end(); ++iter1)
{
   int somevalue  = (*iter)->value;

}

很明显,如果vectorOfFoo中的指针很远,我认为引用的局部性有些丢失。

如果在循环之前我对向量进行迭代之前对其进行排序,性能会怎样?我应该在重复取消引用中有更好的表现吗?

我是否确保连续的“new”分配在内存布局中接近的指针?

【问题讨论】:

  • 抱歉,还有什么问题?你有简介吗?
  • 我想知道在内存布局中使用一个连续的指针数组进行迭代是否更好。
  • 指针在内存中必然是连续的,这是由向量保证的。
  • 在极少数情况下,排序可能会有所帮助。但是,在这些情况下,您可能会更好地控制数据的实际分配方式。
  • @lineello:“还是没有”?那是替代方案吗?好的,那么我会选择“不”,因为这样一来,世界上所有其他事物都在锅中,包括像针织这样简单得可笑的企业。

标签: c++ performance sorting pointers dereference


【解决方案1】:

只是回答你的最后一个问题:不,不能保证 new 分配内存的位置。分配可以分布在整个内存中。根据内存的当前碎片,您可能很幸运,它们有时彼此接近,但不能保证 - 或者实际上可以 - 给出。

【讨论】:

  • 所以你说在这种情况下排序没有用? new 决定分配内存只是运气问题吗?事实上,从一些实验中,我没有找到明确的行为。
  • 该标准当然没有要求从对operator new() 的不同调用中分配的内存的相对位置。实际上,它通常会返回它在其 fre 列表中找到的第一个足够大(但不是太大)的块。您可以创建一个自定义分配器并使用它进行分配以获得更好的控制,至少在 C++ 2011 中是这样。
【解决方案2】:

如果您想提高对象的引用位置,那么您应该研究池分配。

但如果没有分析,那将毫无意义。

【讨论】:

    【解决方案3】:

    这取决于许多因素。

    首先,这取决于从向量指向的对象是如何分配的。如果它们被分配在不同的页面上,那么您只能修复分配部分和/或尝试使用软件预取。

    您通常可以检查 malloc 给出的虚拟地址,但作为较大程序的一部分,单独分配的结果是不确定的。所以如果你想控制分配,你必须做得更聪明。

    在 NUMA 系统的情况下,您必须确保您正在访问的内存是从您的进程正在运行的节点的物理内存中分配的。否则,无论您做什么,内存都将来自另一个节点,在这种情况下您无法做太多事情,除非将您的程序转移回其“主”节点。

    您必须检查从一个对象跳转到另一个对象所需的步幅。预取器可以识别 512 字节窗口内的步幅。如果步幅更大,则从预取器的角度来看,您正在谈论随机内存访问。然后它将关闭以不从缓存中驱逐您的数据,您可以做的最好的事情就是尝试使用软件预取。这可能有帮助,也可能没有帮助(总是测试它)。

    因此,如果对指针向量进行排序使得它们所指向的对象以相对较小的步幅连续放置 - 那么是的,您将通过使其对预取硬件更友好来提高内存访问速度。

    您还必须确保对该向量进行排序不会导致更差的收益/损失比。

    附带说明,根据您使用每个元素的方式,您可能希望一次性分配所有元素和/或将这些对象拆分为不同的较小结构并迭代较小的数据块。

    无论如何,您绝对必须在更改前后衡量整个应用程序的性能。这类优化是一项棘手的工作,即使理论上性能应该有所提高,情况也会变得更糟。有许多工具可用于帮助您分析内存访问。例如,缓存研磨。英特尔的 VTune 也是如此。和许多其他工具。所以不要猜测,实验和验证结果。

    【讨论】:

      猜你喜欢
      • 2013-04-28
      • 2012-10-25
      • 1970-01-01
      • 1970-01-01
      • 2014-12-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多