web-dev-qa-db-ja.com

C ++ 11 std :: threadでスタックサイズを設定する方法

私はC++ 11のstd :: threadライブラリに慣れ親しんでいて、つまずきの妨げになりました。

私は最初はposixスレッドのバックグラウンドから来ており、構築前にstd :: threadのスタックサイズをどのように設定するのかと思っていました。

スタックサイズを設定するpthreadの使用は、次のように行われます。

void* foo(void* arg);
.
.
.
.
pthread_attr_t attribute;
pthread_t thread;

pthread_attr_init(&attribute);
pthread_attr_setstacksize(&attribute,1024);
pthread_create(&thread,&attribute,foo,0);
pthread_join(thread,0);

std :: threadを使用するときに同様のことはありますか?

私は次のリファレンスを使用しています:

http://en.cppreference.com/w/cpp/thread

34

私は最初はposixスレッドのバックグラウンドから来ており、構築前にstd :: threadのスタックサイズをどのように設定するのかと思っていました。

できません。 std::threadは標準化されているため、std::threadはこれをサポートしていません。C++では、固定サイズのスタックではなく、マシンにスタックさえ必要ありません。

pthreadは、サポートするハードウェアに関してより制限があり、スレッドごとに一定のスタックサイズがあることを前提としています。 (これを設定できます)

20
Billy ONeal

Loki Astariが既に述べたように、デフォルト以外のスタックサイズを実際に必要とすることは非常にまれであり、通常は間違いか、コーディングの誤りの結果のいずれかです。

  • デフォルトのスタックサイズがニーズに対して大きすぎると感じてそれを減らしたい場合は、そのことを忘れてください。現在、すべての最新のOSは仮想メモリ/オンデマンドコミットを使用しています。つまり、ページにアクセスするまで、メモリは予約されるだけで、実際には割り当てられません。スタックサイズを小さくしても、実際のメモリフットプリントは減少しません。

  • この非常に動作が原因で、OSはデフォルトのスタックサイズを非常に大きな値に設定する余裕があります。例えば。バニラDebianでは、これは8MB(ulimit -s)これは、あらゆるニーズに十分対応できるはずです。それでも限界に達した場合は、コードが間違っているというのが私の最初の考えです。そのため、何よりもまずそれを確認し、物事をヒープに移動し、再帰関数をループに変換する必要があります。

  • これらすべてにかかわらず本当にスタックサイズを変更する必要がある場合(つまり、減らすことは役に立たないため、増やす)、POSIXでは常に を使用できます。プログラムの開始時にsetrlimit を使用して、デフォルトのスタックサイズを増やします。もちろん、これはすべてのスレッドに影響しますが、それを必要とするスレッドだけが実際に追加のメモリを使用します。

  • 最後に大事なことを言いますが、公平に言えば、スタックサイズを小さくすることが理にかなっている場合があります。32ビットシステムに大量のスレッドがある場合、仮想アドレススペースを消費する可能性があります(これも実際のメモリではありません)消費)ヒープに使用できる十分なアドレス空間がなくなるまで。繰り返しますが、 setrlimit はここでの友ですが、より大きな仮想アドレス空間の恩恵を受けるために64ビットシステムに移行することをお勧めします(とにかくプログラムがそれほど大きい場合は、おそらく、追加のRAMも)の恩恵を受けるでしょう。

16
syam

私もこの問題を調査しています。一部のアプリケーションでは、デフォルトのスタックサイズでは不十分です。例:プログラムは、解決している特定の問題に応じて、深い再帰を行います。プログラムは多くのスレッドを作成する必要があり、メモリの消費が問題です。

ここに私が見つけた(部分的な)解決策/回避策の要約があります:

  • linuxでは、g ++は-fsplit-stackオプションをサポートしています。 分割スタックの詳細については、 を参照してください。ここに彼らのウェブサイトからの要約があります:

分割スタックの目的は、必要に応じて自動的に拡大される不連続なスタックを許可することです。これは、小さなスタックから開始する複数のスレッドを実行し、プログラムの必要に応じてスタックを拡大および縮小できることを意味します。

備考:-fsplit-stackは、 goldリンカー を使い始めて初めて機能しました。 clang ++もこのフラグをサポートするようです。私が試したバージョン(clang ++ 3.3)は、フラグ-fsplit-stackを使用してアプリケーションをコンパイルしようとするとクラッシュしました。

  • Linuxでは、アプリケーションを起動する前にulimit -s <size>を実行してスタックサイズを設定します。 sizeは、Kbs単位のスタックサイズです。備考:コマンドunlimit -s unlimitedは、std::threadで作成されたスレッドのサイズに影響を与えませんでした。 ulimit -s unlimitedを使用すると、メインスレッドは大きくなる可能性がありますが、std::threadで作成されたスレッドにはデフォルトのサイズがありました。

  • Visual Studioを使用するWindowsでは、モジュール定義ファイルでリンカー/STACKパラメーターまたは/STACKSIZEを使用できます。これは、作成されるすべてのスレッドのデフォルトサイズです。詳細については、 このリンク を参照してください。コマンドラインツール [〜#〜] editbin [〜#〜] を使用して、任意の実行可能ファイルでこのパラメーターを変更することもできます。

  • Mingw g ++を使用するWindowsでは、オプション-Wl,--stack,<size>を使用できます。何らかの理由で、cygwin g ++を使用する場合、このフラグはメインスレッドのサイズにのみ影響します。

didが機能しないアプローチ:

  • OSXではulimit -s <size>。メインスレッドのサイズにのみ影響します。さらに、pthreadスタックサイズのMac OSXデフォルトは512kBです。

  • setrlimit は、LinuxおよびOSXのメインスレッドのサイズにのみ影響します。 cygwinでは、私にとってはうまくいきませんでした。常にエラーを返すようです。

OSXの場合、唯一の代替手段はboost::threadではなくstd::threadを使用するようですが、標準に固執したい場合、これはいいことではありません。将来、g ++とclang ++がOSXで-fsplit-stackもサポートすることを願っています。

15

Scott Meyersの本Overview of the New C++(C++0x)でこれを見つけました。コメントとして投稿できないので、これは役に立ちますか?

スレッド、ミューテックス、条件変数などの背後にあるプラットフォーム固有のハンドルを取得するための標準APIもあります。これらのハンドルは、スレッドの優先順位の設定、スタックサイズの設定などのメカニズムであると想定されています(スタックサイズの設定に関しては、 Anthony Williams氏は次のように述べています。「スタックサイズの設定をサポートするOSは、すべて異なる方法で実行します。特定のプラットフォーム(native_handleを使用しても問題ない)をコーディングしている場合、そのプラットフォームの機能を使用して、スタックを切り替えます。たとえば、POSIXではスタックの明示的な割り当てとともにmakecontextとswapcontextを使用でき、Windowsではファイバーを使用できます。次に、プラットフォーム固有の機能(リンカーフラグなど)を使用して、デフォルトのスタックサイズを何かに設定します。本当に小さいので、必要に応じてスタックをもっと大きなものに切り替えます。」)

14
billz

たった今自分でこれに対する答えを探していました。

Std :: threadはこれをサポートしていませんが、boost :: threadはサポートしているようです。

特に、 boost :: thread :: attributes を使用してこれを実現できます。

boost::thread::attributes attrs;
attrs.set_stack_size(4096*10);
boost::thread myThread(attrs, fooFunction, 42);
12
Mark