我有一个课程如下:
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));
所有这些对象的单独分段分配似乎不像某些大量分配那么快。
有关在这里寻求最佳策略的想法吗?
答案 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)
这些是小而自包含的对象 - 将它们直接放在队列中而不是放指针。
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
,您的代码将分配一个新的动态内存块,在其中构造对象(即分配x
和y
),然后按指针到该队列的内存块。queue
本身预先分配的较大内存块中的“slot”中构造对象。正如您已经指出的那样,几乎没有大的分配
比许多小的要好。您的代码是:
专门的批量分配器可以删除最后两个问题,但为什么不将它们全部删除?
---编辑3 ---
至于速度,一般动态内存分配昂贵(大约40-50个机器指令用于最佳分配器)。
专用块分配器会快得多,但是你仍然存在内存延迟问题:将所有内容保持在一起可以保证实现更好的缓存局部性,并且比在队列之间重复“跳转”更适合CPU的预取逻辑通过取消引用指针来实现对象。