11

重複の可能性:
pthread_create によって作成されたスレッドは、カーネル スレッドと同じですか?

以下のコードを使用して、pthread_create 関数が作成できるスレッドの最大数をテストします。

#include <pthread.h>
#include <stdio.h>

static unsigned long long thread_nr = 0;

pthread_mutex_t mutex_;

void* inc_thread_nr(void* arg) {
    (void*)arg;
    pthread_mutex_lock(&mutex_);
    thread_nr ++;
    pthread_mutex_unlock(&mutex_);

    /* printf("thread_nr = %d\n", thread_nr); */

    sleep(300000);
}

int main(int argc, char *argv[])
{
    int err;
    int cnt = 0;

    pthread_t pid[1000000];

    pthread_mutex_init(&mutex_, NULL);

    while (cnt < 1000000) {

        err = pthread_create(&pid[cnt], NULL, (void*)inc_thread_nr, NULL);
        if (err != 0) {
            break;
        }
        cnt++;
    }

    pthread_join(pid[cnt], NULL);

    pthread_mutex_destroy(&mutex_);
    printf("Maximum number of threads per process is = %d\n", thread_nr);
}

出力は次のとおりです。

Maximum number of threads per process is = 825

それは pthread_create 関数が作成できるスレッドの最大数ですか?

さらに、以下のコマンドを使用して、システムが許可するスレッドの最大数を表示します。

# cat /proc/sys/kernel/threads-max

そして番号は772432です。

プログラムの出力が の値と等しくないのはなぜthreads-maxですか?

私のOSはFodaro 16で、12コア、48G RAMです。

4

3 に答える 3

11

スレッドごとのスタックのデフォルトサイズは、テストで人為的に制限を課しています。プロセス(初期スレッド)に指定されたデフォルトのスタックは必要に応じて動的に増加しますが、他のスレッドのスタックのサイズは固定されています。デフォルトのサイズは通常、2メガバイトのように非常に大きく、スレッドごとのスタックが病的なケース(深い再帰など)でも十分に大きいことを確認します。

ほとんどの場合、スレッドワーカーはスタックをほとんど必要としません。私が使用したすべてのアーキテクチャで、深く再帰的なアルゴリズムや大きなローカル変数(構造体または配列)を使用しない限り、スレッドあたり64k(65536バイト)のスタックで十分であることがわかりました。

スレッドごとのスタックサイズを明示的に指定するにはmain()、を次のように変更します。

#define MAXTHREADS 1000000
#define THREADSTACK  65536

int main(int argc, char *argv[])
{
    pthread_t       pid[MAXTHREADS];
    pthread_attr_t  attrs;
    int  err, i;
    int  cnt = 0;

    pthread_attr_init(&attrs);
    pthread_attr_setstacksize(&attrs, THREADSTACK);

    pthread_mutex_init(&mutex_, NULL);

    for (cnt = 0; cnt < MAXTHREADS; cnt++) {

        err = pthread_create(&pid[cnt], &attrs, (void*)inc_thread_nr, NULL);
        if (err != 0)
            break;
    }

    pthread_attr_destroy(&attrs);

    for (i = 0; i < cnt; i++)
        pthread_join(pid[i], NULL);

    pthread_mutex_destroy(&mutex_);

    printf("Maximum number of threads per process is %d (%d)\n", cnt, thread_nr);
}

呼び出しattrsによって消費されないことに注意してください。pthread_create()スレッド属性は、スレッドの作成方法に関するテンプレートのように考えてくださいpthread_create()それらはスレッドに与えられた属性ではありません。これは多くの意欲的なpthreadプログラマーをつまずかせるので、最初からすぐに理解したほうがよいものの1つです。

スタックサイズ自体に関しては、少なくともPTHREAD_STACK_MIN(Linuxでは16384、私は信じています)、で割り切れる必要がありますsysconf(_SC_PAGESIZE)。すべてのアーキテクチャでページサイズは2の累乗であるため、十分な大きさの2の累乗を使用すると常に機能するはずです。

また、そこにも修正を追加しました。存在しないスレッド(ループが作成しようとしたが失敗したスレッド)に参加しようとするだけですが、すべてのスレッドに参加する必要があります(すべてのスレッドが確実に機能するようにするため)。

さらに推奨される修正:

スリープを使用する代わりに、条件変数を使用します。各スレッドpthread_cond_wait()に条件変数(ミューテックスを保持している間)で待機()させてから、ミューテックスを解放して終了します。そうすれば、メイン関数は条件変数で()をブロードキャストするだけpthread_cond_broadcast()で、すべてのスレッドが終了できるようになり、各スレッドに参加できるようになり、その数のスレッドが実際に同時に実行されていることを確認できます。コードが現在の状態であるため、一部のスレッドには、スリープから復帰して終了するのに十分な時間があります。

于 2012-09-12T23:45:42.837 に答える
4

理論的には、プロセスが持つことができるスレッドの数に制限はありません。ただし、実際の制限は、すべてのスレッドがリソースを共有するという事実から生じる可能性があります。

これは、ある時点で、たとえば、そのようなスタック領域と共有するリソースが不足しているため、プロセスが特定の数を超えるプロセスを作成できないことを意味します。

于 2012-09-12T12:27:22.040 に答える
2

pthread_create(3)man ページによると、別の制限があります。

RLIMIT_NPROC soft resource limit (set via setrlimit(2)), which limits the number 
of process  for  a real user ID.

でこの制限の値を見つけてみてくださいgetrlimit(2)。それでも値が測定した数値 (825) と一致しない場合は、この制限を で変更してsetrlimit(2)、測定値に影響するかどうかを確認してください。

編集:実際、RLIMIT_NPROC 制限値は、シェル コマンドulimit -u(最大ユーザー プロセスを出力/設定する) で取得した値と同じです。

于 2012-09-12T12:19:26.617 に答える