2016-05-05 4 views
3

これはUsing a thread in C++ to report progress of computationsへのフォローアップの質問です。計算の進捗状況を報告するCの方法は何ですか?

run_difficult_task()を何度も実行するforループがあるとします。ループがどれだけ進んでいるかを推測したいと思います。

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

    run_difficult_task(i); 

    if (i % 100 == 0) { 
    printf("i = %d\n", i); 
    } 
} 

が、そのようなアプローチの主な問題は、run_difficult_task()を実行すると文字通り(無限ループなどで立ち往生されることによって)永久に取るかもしれないということですので、私が進行を取得したいと思います:私は書くために使用しましたループ変数iの値を印刷することによって、毎秒k秒に報告します。

私は様々なプログラミング言語でオブジェクト指向のマルチスレッド(これについてはあまりよく知られていません)に関するかなりの豊富な文献を見つけましたが、Cスタイルでこれを行うことがわかった質問は、時代遅れです。プラットフォームに依存しない、私が欲しいことをするC11の方法はありますか?何もない場合、私はunixとgccで動作するメソッドに興味があります。

注:私ははないは、(例えば、OpenMP、と)並行してrun_difficult_taskのさまざまなインスタンスを実行したいんが、私は、並列にforループと報告メカニズムを実行したいです。


関連:How to "multithread" C codeHow do I start threads in plain C?

+0

別のスレッドではなく、別のプロセスにレポートを作成する方が簡単ですか? – user3528438

答えて

5

のLinux(ともPOSIXシステムでは)alarmライブラリコールを提供しています。これにより、メインスレッドを中断せずに、何もしなくても何かをすることができます。また、本当に必要ないときにマルチスレッドを気にする必要もありません。あなたのようなユースケースのために作成されました。

+0

私はこれを確かにチェックします。 – Matsmath

+0

良い提案。しかし、OPは、このように問題に近づくには、 'run_difficult_task()'がシグナルによる中断に対して頑強であることが必要であることに注意する必要があります。それが問題の多くであるかどうかは、その機能の詳細によって決まります。 –

+0

代替手段は、 'run_difficult_task()'が何らかの形で(メッセージの受け渡しやsomesuchなど)その進捗状況を外部に伝えるようにすることはほぼ確実です。 'run_difficult_task()'は、外部の計測器が実行時に進行状況を監視することを可能にするリングバッファとして機能するメモリバックアップファイルに低オーバーヘッドストアを行うように変更することもできます。最後に、 'gdb'や' perf'のようなツールを使って時間の経過とともにプロセス状態をサンプリングすることができます。 – dho

1

1つのスレッド(ワーカースレッド)または2つ(計算を行うスレッドと、メインが何か他のことをやっている間に出力を表示するスレッド)といくつかのグローバル変数(ugh)を試すことができます。

最初のスレッドは計算を行い、いくつかのグローバル変数を更新します。 2番目の変数(おそらく単純にメインスレッド)は、この変数が変更されたかどうかをチェックしてから、統計を出力します(おそらく、その変数には、パーセントなどの統計が保持されます)。

int ping = 0, working = 0, data; 

// in main thread 
for (/* something */){ 
    // spawn worker thread 
    while (working) { 
     if (ping) printf("%d\n", data), ping = 0; 
    } 
} 

// in worker thread 
working = 1; 
while (/* something */) { 
    // do a lot of computations 
    if (/* some condition */) { 
     if (! ping) { 
      data = /* data */ 
      ping = 1; 
     } 
    } 
} 
working = 0; 
+0

スレッドベースのソリューションを実装するために必ずしもグローバルは必要ありませんが、共有変数が必要です。また、共有変数を含むソリューションを実装する場合は、適切な同期が必要です。この場合、おそらくmutexを介して共有変数へのアクセスを保護することになります。 –

+0

あなたが正しく理解している場合、スレッドが1つしかない場合は、実際には報告メカニズム(printfなど)をrun_difficult_task()の中に入れることを提案していますか?それはあまり役に立たない。 – Matsmath

+0

@Matsmath、いいえ、あなたは正しく理解していませんでした。 _worker thread_はあなたの 'run_difficult_task'です。 'printf'は' '//メインスレッドにあります '' – ForceBru

0

ここで私が頻繁に使用してきたシンプルな時間ベースの進行状況インジケータです:あなたは試みることができることは


void 
progress(int i) 
{ 
    time_t tvnow; 
    static time_t tvlast; 
    static time_t tvbeg; 

    if (tvbeg == 0) { 
     tvbeg = time(NULL); 
     tvlast = tvbeg - 2; 
    } 

    tvnow = time(NULL); 
    if ((tvnow - tvlast) >= 1) { 
     printf("\r%ld: i = %d",tvnow - tvbeg,i); 
     fflush(stdoout); 
     tvlast = tvnow; 
    } 
} 

int i; 
for (i=0; i < 10000; ++i) { 
    run_difficult_task(i); 
    progress(i); 
} 

UPDATE:

run_difficult_task(i)が2秒以上実行されている場合、この更新は行われますか?

いいえ、しかし私は、コードを別の関数に入れるように例を更新しました。これは、自分のコードで通常行っていることです。

run_difficult_task内の進捗関数の呼び出しを追加して、細かい粒度の進捗状況を取得する必要があります。これは自分のコードでも実行します。

しかし、進行状況に経過時間[秒]を追加したことに注目してください。

あなたが、そのことについて世話をしなかった場合は、run_difficult_taskは実行に時間が2秒以上かかる場合は、進捗状況がiをインクリメントすることによって定義されているので、あなたはそれをを定義して、それがを返しまでは進展ありませんいます外側のループによって行われます。

私自身のために、progress関数は任意の数のワーカースレッドから任意の数の進行インジケータを処理できます。

だから、それはあなたに興味があるであろう、と[言う]場合run_difficult_taskjklのようないくつかの内部ループ変数があり、これらは進歩に加えることができます。または、何でもあなたはに報告したいと思います。

+1

'run_difficult_task(i)'が2秒以上実行されている場合は、この更新を行いますか? – Matsmath

+0

いいえ、そうではありません。 – ForceBru

関連する問題