据我所知,std :: stack和所有这些'手工'堆栈的工作速度比应用程序堆栈慢得多。
也许已经有一个好的低级“自行车”? (堆栈实现)。
或者创建新线程并使用它自己的堆栈是个好主意吗?
我如何直接使用应用程序堆栈? (仅限asm {}?)
答案 0 :(得分:4)
std :: stack是具有堆栈语义的c ++对象的集合。它与线程的堆栈或汇编代码中的push和pop intructions无关。
你想做哪一个
'汇编程序'堆栈通常由硬件维护,并且需要各种调用约定,因此您无法选择如何“分配”它或“管理”它。有些架构具有高度可配置的堆栈,但你不会说你在哪个拱门上
如果你想要一个具有堆栈语义的集合并且你用c ++编写,那么std :: stack是你的选择,除非你证明它的速度不够快
答案 1 :(得分:3)
MInner,您确定堆栈操作是/可能是我们应用程序的瓶颈吗?如果没有,我可以赌它,只需使用std :: stack并忘记它。
答案 2 :(得分:3)
std::stack
明显慢于处理器堆栈的唯一方法是它必须从免费存储分配内存。默认情况下,它使用std::deque
进行存储,根据需要以块的形式分配内存。只要你不继续销毁和重新创建堆栈,它就会保留内存而不需要分配更多内存,除非它比以前更大。所以结构代码如下:
std::stack<int> stack;
for (int i = 0; i < HUGE_NUMBER; ++i)
do_lots_of_work(stack); // uses stack
而不是:
for (int i = 0; i < HUGE_NUMBER; ++i)
do_lots_of_work(); // creates its own stack
如果在分析后发现它仍然花费太长时间分配内存,那么你可以预先分配一个大块,这样你只需要在程序启动时进行一次分配(假设你可以找到堆栈大小的上限) )。您需要进入堆栈的内部才能执行此操作,但可以通过派生自己的堆栈类型来实现。这样的事情(未经测试):
class PreallocatedStack : public std::stack< int, std::vector<int> >
{
public:
explicit PreallocatedStack(size_t size) { c.reserve(size); }
};
编辑:这是一个非常可怕的黑客攻击,但它得到了C ++标准的支持。更有品味的是使用保留向量初始化堆栈,但需要额外分配。并且不要尝试以多态方式使用此类 - STL容器不是为此而设计的。
使用处理器堆栈将无法移植,并且在某些平台上可能会在推送之后无法使用局部变量 - 您可能最终必须在汇编中编写所有内容。 (这是一个选项,如果你真的需要计算每个最后一个周期并且不需要可移植性,但请确保使用分析器来检查它是否真的值得)。没有办法使用另一个线程的堆栈,它比堆栈容器更快。
答案 3 :(得分:2)
“手工”堆栈必然比用于函数调用的堆栈慢的基本思想从根本上是有缺陷的。两者的工作方式非常相似,通常接近相同的速度。有利于硬件堆栈的最重要的一点是它经常被使用,以至于该堆栈顶部或靠近顶部的数据几乎总是在缓存中。您创建的另一个堆栈通常不会经常使用,因此任何给定的引用最终都会更新到主内存而不是缓存。
另一方面,您可以更灵活地为堆栈分配内存。您可以为堆栈创建专用的 分配器。当硬件堆栈溢出时,它通常使用内核分配器分配内存。内核分配器通常非常仔细地调整,因此它通常非常有效 - 但它也非常通用。它不能只是为了堆栈分配而写得很好;它必须写成至少合理地进行任何类型的分配。在这个过程中,它能够非常好地做一件事经常会受到一些影响。
创建一个任意慢的堆栈当然是可能的,但没有根本原因,你的堆栈不能与(通常)提供的堆栈一样快(或可能更快) ) 硬件。我会重复一遍:缓慢分配的最大原因是缓存分配,它只是反映了使用情况。
答案 4 :(得分:0)
这取决于您的要求。 如果要在堆栈上推送用户定义的数据类型,则需要“手工”堆栈
对于其他人说,你想要推动你可以使用的对象的整数,字符或指针 ASM { 推 流行的 } 但不要搞砸了