排队对象的分配策略

时间:2012-03-03 02:36:18

标签: c++ memory-management queue

我有一个课程如下:

typedef struct grid_cell_type {
int x;
int y;
grid_cell_type(int x0, int y0){
    x=x0;
    y=y0;
}

} grid_cell;

我将通过队列抽取大约1亿个这些。

现在,这发生如下:

my_queue.push(new grid_cell(x0,y0));

所有这些对象的单独分段分配似乎不像某些大量分配那么快。

有关在这里寻求最佳策略的想法吗?

2 个答案:

答案 0 :(得分:3)

你可以做一个大数组并分配出来。

int allocation_index = 0;
grid_cell_type* cells = new grid_cell_type[100*1000*100];
my_queue.push(&cells[allocation_index++]);

然后你将避免1亿个小消息的开销。然后清理就像delete [] cells;一样简单。

编辑:在这种特殊情况下,Branko所说的可能是你最好的选择。假设您正在使用std::queue,它将自动分配您需要的内存。我建议的更适合更大的物体。

答案 1 :(得分:3)

这些是小而自包含的对象 - 将它们直接放在队列中而不是放指针。

  • 实际上,在64位系统上,假设int是32位(例如,在Visual C ++下),指针将与对象本身一样大!因此,即使您有批量分配器,您仍然需要支付这个价格。
  • 一般的内存分配器不仅时间昂贵,而且还会产生每个对象的开销,在这种情况下会使对象本身相形见绌(不适用于批量分配器)。

虽然可以设计一个相当有效的“批量”分配方案,但我认为回避问题并完全避免单个对象分配更为简单。

---编辑---

您可以将元素推送到std::queue,如下所示:

struct grid_cell {

    grid_cell(int x0, int y0) {
        x=x0;
        y=y0;
    }

    int x;
    int y;

};

// ...

std::queue<grid_cell> q;

q.push(grid_cell(0, 0));
q.push(grid_cell(0, 1));
q.push(grid_cell(0, 2));
q.push(grid_cell(1, 0));
q.push(grid_cell(1, 1));
q.push(grid_cell(1, 2));

对于std::priority_queue,您需要决定如何订购元素。

---编辑2 ---

@Richard您的代码非常不同。

  • 对于每个push,您的代码将分配一个新的动态内存块,在其中构造对象(即分配xy),然后按指针到该队列的内存块。
  • 我的代码直接在由queue本身预先分配的较大内存块中的“slot”中构造对象。正如您已经指出的那样,几乎没有大的分配 比许多小的要好。

您的代码是:

  1. 容易发生内存泄漏
  2. 你为指针支付额外的存储空间,
  3. 容易出现内存碎片和
  4. 正如我已经提到的那样,存在每个对象的开销。
  5. 专门的批量分配器可以删除最后两个问题,但为什么不将它们全部删除?

    ---编辑3 ---

    至于速度,一般动态内存分配昂贵(大约40-50个机器指令用于最佳分配器)。

    专用块分配器会快得多,但是你仍然存在内存延迟问题:将所有内容保持在一起可以保证实现更好的缓存局部性,并且比在队列之间重复“跳转”更适合CPU的预取逻辑通过取消引用指针来实现对象。