5

これは重複する2つの質問です。ヒープに動的なサイズの配列を割り当てるのではなく、大きな配列に対してalloca()を試してみたいと思います。これは、ヒープを割り当てなくてもパフォーマンスを向上できるようにするためです。しかし、印象スタックのサイズは通常かなり小さいと思いますか?alloca()を最大限に活用できるように、スタックのサイズを大きくすることに不利な点はありますか?RAMが多ければ多いほど、それに比例してスタックサイズを大きくすることができますか?

編集1:できればLinux

EDIT2:私は特定のサイズを念頭に置いていません-私はむしろ限界/境界を決定するものを判断する方法を知りたいです。

4

4 に答える 4

10

スタックサイズは(デフォルトで)ほとんどの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
}
于 2013-03-25T23:33:04.467 に答える
4

プログラムのメインスレッドが取得するデフォルトのスタックサイズは、コンパイラ固有(および/またはOS固有)のものであり、スタックを拡大する方法については、適切なドキュメントを参照してください。

プログラムのデフォルトスタックを任意の大きなサイズに拡大できない場合があります。

ただし、指摘されているように、実行時に必要なサイズのスタックを使用してスレッドを作成できる場合があります。

alloca()いずれにせよ、一度割り当てられた大きなバッファよりも多くの利点はありません。何度も解放して再割り当てする必要はありません。

于 2013-03-25T23:35:02.960 に答える
3

alloca()new/の最も重要な違いは、現在の関数から戻るとmalloc()、割り当てられたすべてのメモリalloca()がなくなることです。

alloca()小さな一時データ構造にのみ役立ちます。

ビッグデータ構造はスタックのキャッシュ局所性を破壊し、パフォーマンスにかなりの打撃を与えるため、これは小さなデータ構造にのみ役立ちます。ローカル変数としての配列についても同じことが言えます。

alloca()非常に特殊な状況でのみ使用してください。よくわからない場合は、まったく使用しないでください。

一般的なルールは次のとおりです。ビッグデータ構造(> = 1k)をスタックに配置しないでください。スタックはスケーリングしません。それは非常に限られたリソースです。

于 2013-03-25T23:49:07.190 に答える
2

最初の質問に答えるには:スタックサイズは通常、ヒープサイズに比べて小さいです(これはほとんどのLinuxアプリケーションに当てはまります)。

計画している割り当てが実際のデフォルトのスタックサイズに比べて大きい場合は、(スタックサイズを増やすよりも)ヒープからの動的割り当てを使用する方がよいと思います。メモリの使用(メモリの充填、読み取り、操作)のコストは、おそらく割り当てのコストをはるかに上回ります。このシナリオでスタックから割り当てることによって、測定可能なメリットが得られる可能性はほとんどありません。

于 2013-03-25T23:46:25.547 に答える