MQLによる非同期・マルチスレッドプログラミング - ページ 34

 
Andrei Novichkov:
しかし、本当にスレッドプーリングが必要なタスクがあるのだろうか。スレッドを作って、それを忘れて、なくなるのを待つ」のではなく、ウィリアムズが言うように、まさに「プール」なのですね。そこにはATMの例もあるようだが、私の勘違いでなければ、このような奇跡の柔道を正当化できるタスクは何だろう?そんな仕事はまだ思いつきません。そして、ThreadPoolでは、すべてがすでに行われていて、ドキュメントや例もあります。

正直なところ、std::async とスレッドプールの間には、std::async が自動的にタスクのためのスレッドを作成し、削除することを除いて、今のところあまり意味を見いだせません。
また、スレッドプールを利用するには、あらかじめプログラムで使用するスレッド数を把握し、この数を明示的にプールに設定する必要がある。
スレッドプーリングはスレッド数に対して静的であることが判明しましたが、そうでない場合もあり、断言はできません。
しかし、Williamsの本では、std::threadで実行するタスクが非常に多い場合にスレッドプーリングを推奨しているという。
そして、これはstd::asyncには当てはまらないのかもしれません。私はまだその意味を完全に理解していません。
また、非同期はネットワークソリューションやマルチシンボル戦略で非常に需要があり、負荷のかかる計算にも有効です。
しかし、std::asyncとstd::promiseが標準装備されているため、スレッドプールを作る必要はないと思います。

 

また、dllのプロジェクト 設定についての質問もあります。
コンパイラによって自動的にDLLに組み込まれる未使用の関数を取り除くには?

すでにいろいろな開発環境を試してみましたが、それぞれ未使用の機能を引っ張ってきています。
MSVS_2017は、独自のランタイム依存関係まで引っ張ってくるので、それを取り除くことはできないのでしょう。
そのため、いろいろなIDEを試しましたが、使われていない機能を引っ張ってくることもあります。
どうすればいいのか?

ファイル:
 
Roman:

正直なところ、std::asyncとスレッドプーリングの間には、std::asyncが自動的にタスクのためのスレッドを生成・削除することを除いて、私自身あまり意味を感じていない。
また、スレッドプールを利用するには、あらかじめプログラムで使用するスレッド数を把握し、この数を明示的にプールに設定する必要がある。
スレッドプーリングはスレッド数に対して静的であることが判明しましたが、そうでない場合もあり、断言はできません。
しかし、Williamsの本では、std::threadで実行するタスクが非常に多い場合にスレッドプーリングを推奨しているという。
そして、これはstd::asyncには当てはまらないのかもしれません。私はまだその意味を完全に理解していません。
また、非同期はネットワークソリューションやマルチシンボル戦略で非常に需要があり、負荷のかかる計算にも有効です。
しかし、std::asyncとstd::promiseが標準装備されているため、スレッドプールを作る必要はないと思います。

つまり、非同期の主なポイントは、スレッドプールを使用して、スレッドの作成と削除のオーバーヘッドを取り除くことであり、もし非同期がそれを行わないなら、価値がないのです。

まあ、実は、非同期を悪く考えすぎていたらしい。簡単なテストでは、かなり十分なものであることがわかります。

#include <future>
#include <iostream>
#include <vector>
using namespace std;

int main()
{
    cout << "Main thread id: " << this_thread::get_id() << endl;
    for (int i = 0;  i < 2;  ++ i){
       cout << "------------------------" << endl;
       vector<future<void>> futures;
       for (int i = 0; i < 10; ++i)
       {
          this_thread::sleep_for(1 ms);
          auto fut = async([]{
                              this_thread::sleep_for(1 s);
                              cout << this_thread::get_id() << '\n';
                           });
          futures.push_back(move(fut));
       }
       for (auto &f : futures)
          f.wait();
    }

    cout << endl;
}

Main thread id: 140657228855104

140657228850944
140657220458240
140657212065536
140657203672832
140657195280128
140657186887424
140657178494720
140657170102016
140657161709312
140657153316608
------------------------
140657153316608
140657161709312
140657170102016
140657178494720
140657228850944
140657220458240
140657212065536
140657203672832
140657195280128
140657186887424

2つ目のジョブのバッチでは、asyncは以前に作成されたスレッドを使用し、新しいスレッドを作成していないことがわかります。だから、当然のように水を差すようなことはしていなかったと思うんです。

 
Roman:

また、dllのプロジェクト設定についての質問もあります。
コンパイラによって自動的にDLLの依存関係に引き込まれる未使用の関数を取り除くにはどうすればよいですか?

mingw では、-static オプションを 指定すると、static では pic の生成が停止されます。

 

より厳しい非同期テスト

#include <future>
#include <iostream>
#include <vector>
#include <mutex>
#include <set>
using namespace std;

mutex mtx;
set<thread::id> id;
atomic<unsigned> atm{0};

int main()
{
   for (int i = 0;  i < 10000;  ++ i) {
      vector<future<void>> futures;
      for (int i = 0; i < 10; ++i) {
         auto fut = async(launch::async,[]{
                                           ++ atm;
                                           lock_guard<mutex> lck{mtx};
                                           id.insert( this_thread::get_id() );
                                        });
         futures.push_back(move(fut));
      }
   }

   cout << "executed " << atm << " tasks, by " << id.size() << " threads\n";
}
// cout: executed 100000 tasks, by 10 threads

まあ、ええ、問題なく使えますよ。なぜ、そんなに悪く思ったのだろう。おそらくc++11の黎明期に曲がった実装をしたのでしょう・・・。

SZY: しかし、lanch::asyncポリシーで異常に遅いasync()を、lanch::deferredに置き換えると(+最初のサイクルの終わりにジョブ完了を待つ)、このシンプルなテストは30倍速く動き始めます!!!!マルチスレッドはこれくらいにしましょう ))) 。ということは、自作のスレッドプールを作る余地があるわけで、標準のものよりもずっと早く作れそうですね。

 
Roman:

また、dllのプロジェクト設定についての質問もあります。
コンパイラによって自動的にDLLに組み込まれる未使用の関数を取り除くには?

すでにいろいろなIDEを試しましたが、それぞれのIDEで使われていない機能を引っ張ってきています。
MSVS_2017は、独自の時間依存性まで引っ張ってくるので、それを取り除くことはできないのでしょう。

当たり前のことを、当たり前に、忘れること。
何が、なぜ迷惑なのか?くだらないことは隣人に任せておけばいい)。
高水準言語は、プログラマーが細かいことを気にしないように作られています。ツァーリには関係ないことだ。そう、そして、何が必要で何が不要なのか、どうやって知ることができるのでしょう。コンパイラが一番よく知っている。
 
Vict:

より厳しい非同期テスト

まあ、ええ、問題なく使えますよ。なぜ、そんなに悪く思ったのだろう。おそらくc++11の黎明期に曲がった実装をしたのでしょう・・・。

SZY: しかし、lanch::asyncポリシーで異常に遅いasync()を、lanch::deferredに置き換えると(+最初のサイクルの終わりにジョブ完了を待つ)、このシンプルなテストは30倍速く動き始めます!!!!マルチスレッドはこれくらいにしましょう )) 。ということは、自作のスレッドプールを作る余地があるわけで、標準のものよりもずっと早く作れそうですね。

最後まで読まずに、延期フラグで実行することを提案することにしました ))))理にかなっていると思いますし、そのようなテストが速く走るのであれば、一般的にはこのような使い方が望ましいと思いますが、なぜ厳密な制限を設けるのでしょうか。Gitへのリンクをありがとうございました。)ブースト付きとブーストなしの2種類があるのがよかったです。

ローマン

もうひとつ、DLL用のプロジェクトの設定について質問が出た。
コンパイラによって自動的にDLL依存に引き込まれる未使用の関数を取り除くにはどうすればよいですか?

すでにいろいろな開発環境を試してみましたが、それぞれ独自の未使用の機能を引っ張ってきています。
MSVS_2017は、独自の時間依存性まで引っ張ってくるので、それを取り除くことはできないのでしょう。
そのため、いろいろなIDEを試しましたが、使われていない機能を引っ張ってくることもあります。
どうすればいいのか?

暴言を吐かずにどうするんだ?そうそう、どこも違うんですよね。いや、ランタイムがなければ押しも押されもしないのだが ))))あなたはまだQTを使ったことがないようですが、そこにはDLLソーセージの花輪が全部引かれているんですよ。


 
Andrei Novichkov:

最後まで読まずに、延期フラグで実行することを提案することにしました )))



なぜ、async()にdeferredフラグが必要なのか?本当に理解できないのですが、説明してもらえますか?

 
Vict:

なぜ、async()にdeferredフラグが必要なのか?本当に理解できないのですが、説明してもらえますか?

実際、ドキュメントでフラグについて読んでみてはいかがでしょうか。https://en.cppreference.com で .また、stackoverflow.comでのディスカッションを含む例もあります。私は普段からこれらの情報源を利用していますが、皆さんもそうすることをお勧めします。

 
Andrei Novichkov:

実際にドキュメントでフラグについて読んでみてはいかがでしょうか。https://en.cppreference.com で .また、stackoverflow.comでのディスカッションを含む例もあります。私は普段からこれらの情報源を利用しているので、皆さんもそうすることをお勧めします。

MSDN完全なドキュメントです。あとは補足資料です。