为 C++ 预分配空间STL队列
我正在使用队列编写基数排序算法,我希望在开始向队列添加内容之前让 STL 队列分配空间,这样我就可以避免不断的动态调整大小操作。
即使这不存在,我想要一些具有...效果的东西,
queue<int> qs(N);
for(int i=0;i<N;++i)
qs.push(rand());
这样它就不会在循环期间动态分配任何内存。
有问题的实际代码...
void radix_sort()
{
// Biggest number?
int max=-1;
for(int i=0;i<N;++i)
if(a[i]>max)
max = a[i];
// How many digits in it
int maxdigits=1;
while(max /= 10) maxdigits++;
// Create some buckets.
deque<int> b[10];
for(int i=0;i<10;++i)
b[i] = deque<int>(N);
int div=1;
// Radix Sort by digits
for(int d=1;d<=maxdigits;++d)
{
if(d>1)
div*=10;
// Queue
for(int i=0;i<N;++i)
b[ (a[i]/div) % 10 ].push_front(a[i]);
// Dequeue
int k=0;
for(int q=0;q<10;++q)
while(b[q].size() > 0)
{
a[k++] = b[q].back();
b[q].pop_back();
}
}
}
I'm writing a radix sort algorithm using queues and I would like to have a STL queue allocate space before I start adding things to the queue so that I can avoid constant dynamic resizing operations.
Even though this doesn't exist, I want something with the effect of...
queue<int> qs(N);
for(int i=0;i<N;++i)
qs.push(rand());
in such a way that it will not dynamically allocate any memory during the loop.
The actual code in question...
void radix_sort()
{
// Biggest number?
int max=-1;
for(int i=0;i<N;++i)
if(a[i]>max)
max = a[i];
// How many digits in it
int maxdigits=1;
while(max /= 10) maxdigits++;
// Create some buckets.
deque<int> b[10];
for(int i=0;i<10;++i)
b[i] = deque<int>(N);
int div=1;
// Radix Sort by digits
for(int d=1;d<=maxdigits;++d)
{
if(d>1)
div*=10;
// Queue
for(int i=0;i<N;++i)
b[ (a[i]/div) % 10 ].push_front(a[i]);
// Dequeue
int k=0;
for(int q=0;q<10;++q)
while(b[q].size() > 0)
{
a[k++] = b[q].back();
b[q].pop_back();
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
这很可能不是问题。无论如何,Deque 都是以块的形式分配的,因此您可能只会重新分配几次。您确定这是瓶颈吗?
无论如何,该标准没有提供“队列”容器的访问器,因为这会破坏封装的目的。
如果您真的担心,请进行池分配。这意味着预先分配内存,因此当容器请求内存时,它已经在那里了。我无法真正回顾分配器和亲属,这对于 SO 答案来说太过分了,但是请查找 Google 上的分配器。
基本上,您可以告诉容器从哪里获取内存。通常,这是默认分配器,它使用 new 和 delete。
Boost 提供了 池分配器,它会像这样:
池预先分配内存,因此在
期间不会完成实际的内存分配>push()
/pop()
。我使用
list
而不是deque
因为它更简单。通常,双端队列
优于list
,但有了分配器,赋予deque
优势的东西(例如缓存性能和分配成本)不再存在。因此,list
使用起来要简单得多。您还可以使用循环缓冲区,例如这样的:
Chances are this is not a problem.
Deque
's allocate in chunks anyway, so you'll probably only reallocate a few times. Have you determined this to be a bottleneck?Anyway, the standard does not give an accessor to the `queue''s container, because that would defeat the purpose of encapsulation.
If you're really worried, pool allocate. This means preallocate the memory upfront, so when the container asks for memory, it's already there. I can't really go over allocators and kin, that would be overkill for an SO answer, but look up allocators on Google.
Basically, you can tell your container where to get it's memory from. Normally, this is the default allocator, which uses new and delete.
Boost provides a pool allocator, and it would go something like this:
The pool allocates the memory up-front, so no actual memory allocation is done during
push()
/pop()
.I used a
list
instead of adeque
because it is simpler. Normally, adeque
is superior to alist
, but with an allocator, the things that gave thedeque
it's advantage, like cache-performance and allocation cost, no longer exist. Therefore, alist
is much simpler to use.You can also use a circular buffer, like such:
您可以尝试使用 std::deque 代替......
You could try using a std::deque instead...
如果您使用其中一种结构来组成支持“reserve”函数调用的队列,那么您应该会很好。如果此数据结构不能满足您的需求,您可能需要寻找另一种。
话虽如此,您确定这里存在性能问题吗?
雅各布
If you use one of the structures to compose your queue that supports the "reserve" function call you should be good. If this data structure does not support your needs, you might want to look for another one.
That being said, are you sure there is a performance problem here?
Jacob
听起来您需要一个带有 Reserve() 方法的数据结构,以及来自两端的高效“推送”和“弹出”操作。包裹在 std::vector 周围的环形缓冲区怎么样?您可以在构造函数中保留()所需的空间,然后在实现中维护“front”和“end”索引,以将公共接口中的“push”和“pop”操作转换为底层 std 上的 O(1) 操作::向量。
It sounds like you need a data structure with a reserve() method, and efficient "push" and "pop" operations from opposite ends. How about a ring buffer, wrapped around a std::vector ? You could reserve() the space you need in the constructor, then maintain "front" and "end" indices in your implementation to translate "push" and "pop" operations in the public interface to O(1) operations on the underlying std::vector.
这是一个非常古老的问题,但我没有看到 OP 问题的答案:How can I usespecial std::queue with a pre-allocated buffer。所以这里是:
我不知道不需要自定义分配器的解决方案。但是,如果您可以使用自定义分配器,则可以实现您想要的目标。
概念证明示例代码可在 https://github.com/vincetse/allocator 获取,我将抄袭如下:
This is a very old question, but I didn’t see an answer to OPs question: How can I use specifically std::queue with a pre-allocated buffer. So here goes:
I’m not aware of a solution that doesn’t require a custom allocator. However if you can use a custom allocator, you can achieve what you’re looking for.
Proof of concept example code is available at https://github.com/vincetse/allocator which I will plagiarize below:
看看这是否有帮助:http://www.cs.sunysb。 edu/~skiena/392/programs/queue.c
see if this helps: http://www.cs.sunysb.edu/~skiena/392/programs/queue.c
不用队列,用列表代替怎么样?
Instead of a queue, how about use a list instead?