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

Increase stack size to use alloca()?

本文关键字:alloca 堆栈 增加      更新时间:2023-10-16

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

EDIT1:最好是Linux

我没有一个特定的大小,我宁愿知道如何判断是什么决定了限制/边界。

堆栈大小(默认情况下)在大多数unix-y平台上为8MB,在Windows上为1MB(也就是说,因为Windows有一种确定性的方式来恢复堆栈外问题,而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
}

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

您可能无法将程序的默认堆栈扩展到任意大的大小。

但是,正如前面所指出的,您可以在运行时创建一个具有您想要的堆栈大小的线程。

在任何情况下,alloca()与一次分配的大缓冲区相比没有太大的好处。您不需要多次释放和重新分配它。

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

alloca()只适用于小型临时数据结构。

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

仅在非常特殊的情况下使用alloca()。如果不确定,请不要使用。

一般规则是:不要将大数据结构(>= 1k)放在堆栈上。堆栈不能扩展。这是一个非常有限的资源。

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

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