代码之家  ›  专栏  ›  技术社区  ›  intrigued_66

增加堆栈大小以使用alloca()?

  •  5
  • intrigued_66  · 技术社区  · 13 年前

    这是两个重叠的问题——我希望尝试大型数组的alloca(),而不是在堆上分配动态大小的数组。这样我就可以在不进行堆分配的情况下提高性能。然而,我得到的印象堆栈大小通常都很小?增加堆栈的大小以便充分利用alloca()有什么缺点吗?是不是我的RAM越多,我就可以按比例增加堆栈大小?

    第1版:最好是Linux

    编辑2:我心中没有指定的尺寸——我更想知道如何判断是什么决定了极限/边界。

    4 回复  |  直到 13 年前
        1
  •  10
  •   Billy ONeal IS4    13 年前

    在大多数unix-y平台上,堆栈大小(默认情况下)为8MB,在Windows上为1MB(即,因为Windows具有 a deterministic way for recovering from out of stack problems ,而unix-y平台通常抛出 SIGSEGV 信号)。

    如果您的分配很大,那么在堆上分配和在堆栈上分配之间不会有太大的性能差异。当然,堆栈的每次分配效率略高,但如果您的分配很大,那么分配的数量可能会很小。

    如果你想要一个更大的类似堆栈的结构,你可以随时编写自己的分配器,它从malloc获得一个大块,然后以类似堆栈的方式处理分配/释放。

    #include <stdexcept>
    #include <cstddef>
    
    class StackLikeAllocator
    {
        std::size_t usedSize;
        std::size_t maximumSize;
        void *memory;
    public:
        StackLikeAllocator(std::size_t backingSize)
        {
            memory = new char[backingSize];
            usedSize = 0;
            maximumSize = backingSize;
        }
        ~StackLikeAllocator()
        {
            delete[] memory;
        }
        void * Allocate(std::size_t desiredSize)
        {
            // You would have to make sure alignment was correct for your
            // platform (Exercise to the reader)
            std::size_t newUsedSize = usedSize + desiredSize;
            if (newUsedSize > maximumSize)
            {
                throw std::bad_alloc("Exceeded maximum size for this allocator.");
            }
    
            void* result = static_cast<void*>(static_cast<char*>(memory) + usedSize);
            usedSize = newUsedSize;
            return result;
        }
    
        // If you need to support deallocation then modifying this shouldn't be
        // too difficult
    }
    
        2
  •  4
  •   Alexey Frunze    13 年前

    程序的主线程获得的默认堆栈大小是编译器特定的(和/或操作系统特定的),您应该查看适当的文档来了解如何扩大堆栈。

    可能发生的情况是,您可能无法将程序的默认堆栈放大到任意大的大小。

    然而,正如已经指出的那样,您可以在运行时创建一个具有所需大小堆栈的线程。

    无论如何 alloca() 在曾经分配的大缓冲区上。你不需要多次释放和重新分配它。

        3
  •  3
  •   Johannes Overmann    13 年前

    两者之间最重要的区别 alloca() new / malloc() 是所有分配的内存 分配() 将在您从当前功能返回时消失。

    分配() 仅适用于小型临时数据结构。

    它只对小数据结构有用,因为大数据结构会破坏堆栈的缓存位置,这会给您带来相当大的性能打击。作为局部变量的数组也是如此。

    使用 分配() 只有在非常特殊的情况下。如果不确定,请不要使用它。

    一般规则是:不要将大数据结构(>=1k)放在堆栈上。堆栈不按比例缩放。这是一种非常有限的资源。

        4
  •  2
  •   Mark Wilkins    13 年前

    回答第一个问题:相对于堆大小,堆栈大小通常很小(这在大多数Linux应用程序中都适用)。

    如果您计划的分配很大 相对的 到实际的默认堆栈大小,那么我认为最好使用堆中的动态分配(而不是试图增加堆栈大小)。使用内存的成本(填充、读取、操作)可能会远远超过分配的成本。在这种情况下,通过从堆栈中进行分配,您不太可能看到可衡量的好处。