web-dev-qa-db-ja.com

pthreadのデフォルトのスタックサイズ

Linuxでのpthreadのデフォルトのスタックサイズは16Kです。 64ビットのUbuntuインストールで奇妙な結果が出ます。

$ ulimit -s
8192

また:

pthread_attr_init(&attr);
pthread_attr_getstacksize(&attr, &stacksize);
printf("Thread stack size = %d bytes \n", stacksize);

Prints
    Thread stack size = 8388608 bytes

スタックサイズが「8388608」ではないことは確かです。何が悪いのでしょうか?

24
Kamath
_int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize);
_

stacksize属性は、作成されたスレッドスタックに割り当てられる最小スタックサイズ(バイト単位)を定義します。

あなたの例では、スタックサイズは、コマンド_ulimit -s_によって返される8MBに対応する8388608バイトに設定されています。

pthread_create()の説明から:

Linux/x86-32では、新しいスレッドのデフォルトのスタックサイズは2メガバイトです。 NPTLスレッド実装では、プログラム開始時のRLIMIT_STACKソフトリソース制限に「無制限」以外の値がある場合、新しいスレッドのデフォルトのスタックサイズが決定されます。 pthread_attr_setstacksize(3)を使用すると、デフォルト以外のスタックサイズを取得するために、スレッドの作成に使用されるattr引数でスタックサイズ属性を明示的に設定できます。

そのため、スレッドスタックサイズは、上記のset関数またはulimitシステムプロパティを介して設定できます。あなたが言及している16kの場合、どのプラットフォームでそれを見たのか、システム制限が設定されているのかどうかは不明です。

これに関する興味深い例については、 pthread_create page および here を参照してください。

22
fduff

実際には、あなたのvirtualスタックサイズis 8388608バイト(8 MB)。もちろん、これは正しくない可能性があると結論するのは自然です。これは、99%の時間で数KBがおそらく必要なすべてのものである場合に、すべてのスレッドがスタックのために消費する途方もなく大量のメモリであるためです。

良いニュースは、スレッドが実際に必要な物理メモリの量のみを使用することです。これは、プロセッサでハードウェアのメモリ管理ユニット(MMU)を使用することによってOSが得る魔法の力の1つです。ここで何が起こるかです:

  1. OSは、MMUのページテーブルをスレッドに設定することにより、スタックに8 MBの仮想メモリを割り当てます。 RAMはページテーブルエントリのみを保持するために必要です。

  2. スレッドが実行され、物理ページがまだ割り当てられていないスタック上の仮想アドレスにアクセスしようとすると、「ページフォールト」と呼ばれるハードウェア例外がMMUによってトリガーされます。

  3. CPUコアは、特権実行モード(独自のスタックを持つ)に切り替えて、カーネル内のページフォールト例外ハンドラー関数を呼び出すことにより、ページフォールト例外に応答します。

  4. カーネルは物理RAM=のページをその仮想メモリページに割り当て、ユーザー空間スレッドに戻ります。

ユーザー空間のスレッドは、その作業をまったく認識しません。その観点からは、まるでメモリがそこにあるかのようにスタックを使用するだけです。その間、スタックはスレッドのニーズを満たすために自動的に増加します(または増加しません)。

MMUは、今日のコンピュータシステムのハードウェアの重要な部分です。特に、それはシステムの多くの「魔法」の原因です。そのため、=の詳細について学ぶことを強くお勧めしますMMUは、一般的に仮想メモリについてです。また、アプリケーションがパフォーマンスに敏感で、大量のデータを処理する場合、TLB(MMUのページテーブルキャッシュ)がどのように機能するかを理解する必要があります。 TLBヒット率を最大化するためにデータまたはアルゴリズムを再構築する方法。

47
jtchitty