2017-03-01 7 views
0

私は、待ち時間(分)が非常に長く、リソース消費量が非常に少ない多数のタスク(>> 100K)を持っています。潜在的にそれらはすべて並行して実行される可能性があり、私はstd::asyncを使用して各タスクの未来を生成することを検討していました。std :: asyncが非同期で作成して実行するスレッドの最大数はいくらですか?

私の質問はです。std :: asyncが非同期で作成して実行するスレッドの最大数はいくらですか? (Ubuntu 16-xxまたはCentOS 7.x-x86_64でg ++ 6.xを使用)

実際に実行している(待機している)タスクが十分にない場合は、レイテンシのコストは非常に高くなります。答えに到達するために

は、私は、システムの機能をチェックして開始しました:

[email protected]:~/programming/cxx/async$ ulimit -u 
43735 
[email protected]:~/programming/cxx/async$ cat /proc/sys/kernel/threads-max 
87470 

これらの数字から、私が実行して43Kのスレッドのために取得することができるように期待していた(ほとんどが待っています)並行して。それを確認するために、私は個別のスレッドIDの数を確認するには、以下のプログラムを書いて、空のタスクと100K std::asyncを呼び出すために必要な時間:

#include <thread> 
#include <future> 
#include <iostream> 
#include <vector> 
#include <algorithm> 
#include <chrono> 
#include <string> 

std::thread::id foo() 
{ 
    using namespace std::chrono_literals; 
    //std::this_thread::sleep_for(2s); 
    return std::this_thread::get_id(); 
} 

int main(int argc, char **argv) 
{ 
    if (2 != argc) exit(1); 
    const size_t COUNT = std::stoi(argv[1]); 
    std::vector<decltype(std::async(foo))> futures; 
    futures.reserve(COUNT); 
    while (futures.capacity() != futures.size()) 
    { 
     futures.push_back(std::async(foo)); 
    } 
    std::vector<std::thread::id> ids; 
    ids.reserve(futures.size()); 
    for (auto &f: futures) 
    { 
     ids.push_back(f.get()); 
    } 
    std::sort(ids.begin(), ids.end()); 
    const auto end = std::unique(ids.begin(), ids.end()); 
    ids.erase(end, ids.end()); 
    std:: cerr << "COUNT: " << COUNT << ": ids.size(): " << ids.size() << std::endl; 
} 

時間は大丈夫だったが、異なるスレッドIDの数ははるかにました(32748の代わり43735)予想より少ない:

[email protected]:~/programming/cxx/async$ /usr/bin/time -f "%E" ./testAsync 100000 
COUNT: 100000: ids.size(): 32748 
0:03.29 

それから私はfooでのスリープ・ラインは2S睡眠時間を追加するために非コメント。得られたタイミングは10Kタスク程度まで2Sと一致するが、それを超えていくつかの点で、いくつかのタスクは、エンドアップ同一のスレッドIDと各追加のタスクの2Sによる経過時間増加を共有:

[email protected]:~/programming/cxx/async$ /usr/bin/time -f "%E" ./testAsync 10056 
COUNT: 10056: ids.size(): 10056 
0:02.24 
[email protected]:~/programming/cxx/async$ /usr/bin/time -f "%E" ./testAsync 10057 
COUNT: 10057: ids.size(): 10057 
0:04.27 
[email protected]:~/programming/cxx/async$ /usr/bin/time -f "%E" ./testAsync 10058 
COUNT: 10058: ids.size(): 10057 
0:06.28 
[email protected]:~/programming/cxx/async$ ps -eT | wc -l 
277 

だから、私の問題は、このシステムでは、限界は10Kのオーダーであると考えています。私は別のシステムでチェックし、限界は4Kのオーダーでした。

私は理解することはできません。

  • をこれらの値は、簡単な
  • は、Linux上のシステムグラムで
+0

これらのスレッドはそれぞれ、OSからいくつかのリソースを取得する必要があります。スレッドスタックの標準的なデフォルトサイズは8MBなので、そのために合計_thread-count * 8MBのDRAMが必要です。より多くのスレッドを起動するだけでなく、リソースも必要です。[こちら](http://stackoverflow.com/questions/25814365/when-to-use-stdasync-vs-stdthreads)も参照してください。 – Arash

+0

ほとんど同じくらいばかげた数の処理コアがないばかげた数のタスクはそれほど有用ではありません。スレッドは、プロセッサにアクセスするために時間を費やすのに多くの時間を費やします。スレッドプールの使用を検討してください。 – user4581301

+0

@arashリンクに感謝します。 DRAMの使用に関しては、デフォルトのスレッドスタックサイズが8MBであっても、これが仮想メモリであると予想され、実際に必要なDRAMの量はスレッドが実際に使用しているもの(ページサイズに切り上げたもの)になります。私が間違っている? –

答えて

0

++の仕様から、これらの値を予測する方法が非常に小さいので、なぜ答えは "pthread_createが失敗してEAGAINを返す前に作成できるスレッドの最大数"のようです。その数は、いくつかの異なる値とman pthread_createリストによってそれらの3を制限することができます。

  • RLIMIT_NPROC:(私のUbuntu/VirtualBoxのラップトップ上で私のCentOS 7サーバーと43735の4096)ソフト資源制限
  • /proc/sys/kernel/threads-maxの値(2061857および87470 RESP。)
  • /proc/sys/kernel/pid_max(40960及び32768 RESPの値。)

man logind.confが示すようsystemdによって課される少なくとも一つの他の可能な限界がある。

UserTasksMax =各ユーザーが同時に実行できるOSタスクの最大数を設定します。これは、ユーザごとのスライス単位のTasksMax =設定を制御します。詳しくは、systemd.resource-control(5)を参照してください。デフォルトは33%で、カーネルのデフォルトはホスト上で10813になりますが、OSコンテナでは小さくなる可能性があります。

関連する問題