0

ループが実行されている次のサンプルプログラムについて考えてみます。

int main()
{

  for (int i = 0; i<= 300; ++i) {

  }

}

iかなり基本的なことですが、今度は毎秒の値を出力したいとします。

cout << "i= " << i << "\n";

次のような単純なループで十分な場合があります。「elaspedTime」は、プログラムが実行されている秒数を含む架空の整数であり、OSによって魔法のように更新されます。

int lastTime = 0;
while (true) {
  if (elapsedTime > lastTime) { // Another second has passed
    cout << "i= " << "\n";
    lastTime = elapsedTime;
  }
}

ここでの最終的な目標は、次のような出力を提供することです(ループが、古くて遅いCPU上にあったため、ループが1秒間に正確に100回実行されたと仮定します)。

$ ./myprog
i= 100
i= 200
i= 300

これらは単純な関数とルーチンですが、それにもかかわらず、通常は関数だけを持つ「古典的な」c++プログラムでそのような操作を実行する方法はわかりませんmain()。単純さにもかかわらず、これは私がマルチスレッドを学ぶ必要があるポイントですか?または、関数を呼び出しmain()て、その戻りを待たずに、呼び出された関数がスレッドを「占有」しないようにすることは可能ですか?

4

3 に答える 3

3

2つの関数を互いに独立して同時に正確に実行する場合は、スレッドを使用する必要があります。あなたが提供した例は、あなたが達成したいと述べたことを達成するためにスレッドを使用する必要はありませんが、あなたのコメントに基づいて、あなたの質問は少し不明確だったと思います。

マルチスレッドは、C++03標準では言及されていないものです。最新のC++11標準ではある程度のサポートがありますが、すべてを網羅しているわけではありません。マルチスレッドが実際に実装される方法は、プラットフォーム固有です。WinTelボックスはある方法でそれを行い、Linux/Intelボックスは別の方法でそれを行います。マルチスレッドコードを作成するための2つの主なアプローチは次のとおりです。

  1. プラットフォーム固有の機能を使用します。
  2. クロスプラットフォームのスレッドライブラリを使用します。

始めたばかりのときは、最近はクロスプラットフォームライブラリから始めることをお勧めします。そうすれば、プラットフォーム固有の特異性に惑わされることなく、全体像の概念の多くを理解することができます。そのようなライブラリの1つがBoost.Threadです。

編集

あなたがマルチスレッドプログラミングに不慣れであることを考えると、私はあなたに警告しなければならないと感じます:あなたは目隠しをして深いウサギの穴を飛び降りています。マルチスレッドプログラミングはチェスのようなものです。基本的な構文とシステムコールの多くをかなりすばやく学ぶことができますが、マルチスレッドプログラミングを正しく行うことは、多くの研究と実践が必要になるだけです。正しく行われるマルチスレッドプログラミングは、プログラマーがこれまで直面する中で最も困難なことの1つです。

また、以下の@CrazyEddieのコメントにも特に注意してください。

ストーリーは変わりますが、「機能」から「タスク」に切り替えると。タスクによっては、一度に多くのタスクを実行することは非常に可能です。OPのようなイベントループは通常、ほとんどの時間をスリープ状態に費やすため、スレッドは通常、パフォーマンスや必要性ではなく、利便性のためにのみ使用されます。あなたはこれを知っていると確信していますが、OPはおそらく知らないでしょう。OPは、「非同期処理」を調べて、スレッドを使用することのメリットとペナルティを、非ブロッキングのopsとイベントループと比較する必要があります。

于 2012-05-09T15:19:03.897 に答える
1

これを行うことの何が問題になっていますか?マルチタスクは必要ありません。

int lastTime = 0;
while (true) {
  if (std::time() > lastTime) { // Another second has passed
    cout << "i= " << i << "\n";
    // potentially expensive code goes here, which updates "i"
    lastTime = std::time();
  }
}
于 2012-05-09T15:07:54.830 に答える
0

でも、あなたがどんな問題を解決しようとしているのか知りたいです。「1秒間に何回の反復が行われるかを知りたい」というのはどこから来たのでしょうか。私が尋ねている理由は、冒頭で説明したシングルスレッドアプローチ(チェッククロック-増分-チェッククロック-増分...チェッククロック-印刷)またはマルチスレッドアプローチのいずれかを使用して得られる答えであるためです。どちらも、実行中のスレッドのオーバーヘッドと不確実性の導入に悩まされています。つまり、どちらの場合も、多数の追加処理を実行する必要があります。シングルスレッドの場合はclock()呼び出し、マルチスレッドの場合はスレッド同期です。どちらも、プログラムによって1秒間に実行される反復の総数に影響を与えるため(数は少なくなります)、誤った結果が得られます。さらにあります ■スレッドが実行され、次に使用可能なクォンタムを待機するときにスレッドスケジューラが決定するのは、オペレーティングシステムのスレッドスケジューラです。また、クォンタムは約20〜30ミリ秒であるため、時間間隔のチェック中に発生するエラーは、簡単に(おそらく平均して)数パーセントになる可能性があります。

開始時間を節約し、すべてのデータを処理するために必要なすべての反復を実行し(すべての作業を実行)、タイムスタンプを再度取得して、反復の総数を時間で割る方が簡単で自然ではないでしょうか。間隔。または、このアプローチが機能しないという、解決しようとしている問題に固有の何かがありますか?

于 2012-05-10T19:03:31.963 に答える