2015-11-12 11 views
6

私は並列コンピューティングの基礎を学びたいと思っていますが、私は自分のコンピュータ上で問題に遭遇しています。以下のコードを見てください。基本的には、「Hello World!」という行を印刷したいと思います。私のコンピュータにはすべてのコアがあります。私のコンピュータは4つのコアを持っているので、その行を4回印刷するべきです。 'printf'行の代わりにコメントアウトされた 'cout'行を使用すると、出力がすべて混乱することになります。これは、 '\ n'エスケープコマンドが「Hello World!」とは別に実行されるため、新しい行出力がランダムに発生するためです。 'printf'行はこの問題の解決策です。なぜなら、行はすべて一度に実行されるからです( 'cout'行のように分割されないため)。しかし、私が 'printf'を使うと、私の出力はまるで私が 'cout'を使ったかのように混乱します。なぜそれがこれを行うのか分かりません。私は別のコンピュータで全く同じコードを試してみましたが、完全に動作します。それは 'printf'で出力をつまずくだけの私のコンピュータです。 CS教授にメールを送りました。私のCS教授にメールを送りました。私のCS教授に私のコンピュータでこれをやっている理由が分かりません。私は自分のコンピュータにOpenMPを正しくセットアップしたことを知っています。並列コンピューティングの経験を持つ人は、なぜこれが私のコンピュータ上で乱れているのかを知っていますか?パラレルコンピューティング - 混乱した出力?

こんにちは

Hello Worldの臥:

#include <omp.h> 
#include <stdio.h> 
#include <iostream> 
#include <stdlib.h> 
using namespace std; 

int main() 
{ 
    #pragma omp parallel 
    { 
     printf("Hello World!\n"); 
     //cout << "Hello World!\n" << endl; 
    } 
    return 0; 
} 

私が話しているかを示すために、ここで私は自分のコンピュータ上で上記のコードを実行したときの出力があります!

rld!

こんにちは!

+0

私はちょうど 'cout'で試してみましたが、完璧に動作しました:http://ideone.com/dPPQeO –

+0

出力バッファをフラッシュする際、' endl'の部分があなたの問題の原因かもしれません。 –

+4

これは、あなたが物事を並行して実行するときに起こると思われるものです。コア2の途中でコア1のprintfが実行されるのを妨げるものは何もありません。この種のことが、並列プログラミングが難しい理由です。 – immibis

答えて

6

申し訳ありませんが、あなたの教授は誤解しています。共有リソース(この場合はSTDOUT出力ファイル)の途切れることのない使用を保証するには、相互排他性またはその他の障壁を利用する必要があります。

printfまたはstd::cout::operator<<()にかかわらず、混在出力が予想される可能性があります。表示される動作の違いは、それぞれ異なるデザインのため、それぞれの実行時間の微妙な違いです。どちらの場合でもこの動作が必要です。

私はそれが他の人のために働く理由を理解できません。

そうではありません。あなたのクラスのヒーローになり、それがどのように動作し、どのように修正するかを説明してください。彼らに彼らの愛を送ると伝えてください。 :)

4

すでに説明したように、printf()はアトミックであり、出力をマングリングしませんが、std::cout::operator<<()は基本的に間違っていると混乱します。

しかし、これには「真実」の部分がありますが、それは別のレベルです。例を挙げましょう:

私はこれを与えるかもしれないOpenMPの "Hello World" のC-スタイルを、しようとした場合:

printf("Hello from thread %d of %d\n", 
     omp_get_thread_num(), 
     omp_get_num_threads()); 

同じ1 C++ - スタイルは次のようになります。

std::cout << "Hello from thread " << omp_get_thread_num() 
      << " of " << omp_get_num_threads() 
      << std::endl; 

そして、両者の間に本質的な違いはprintf()のために、私はC++ながら、完全に準備出力文字列で、一度印刷メソッドを呼び出すことである - スタイル1は、行の唯一のこまごまとし、std::cout::operator<<() 5回を呼び出しますそれは送られても送られなくてもよい標準出力。 内部的には、何かが起こる可能性があり、私は何らかの振る舞いをするつもりはありません。しかし、少なくともここではprintf()を使用することで、保証できない場合でも、私はきれいな出力が得られる可能性が高くなります。ここで

は完全な例である:私のLinuxラップトップ上で(GCC 5.2)私を与え

#include <iostream> 
#include <stdio.h> 
#include <omp.h> 

int main() { 
    #pragma omp parallel 
    printf("Hello from thread %d of %d with printf()\n", 
      omp_get_thread_num(), 
      omp_get_num_threads()); 

    printf("*** outside of parallel region ***\n"); 

    #pragma omp parallel 
    std::cout << "Hello from thread " << omp_get_thread_num() 
       << " of " << omp_get_num_threads() 
       << " with std::cout" 
       << std::endl; 
    return 0; 
} 

~/tmp$ g++ -fopenmp stdout.cc 
~/tmp$ ./a.out 
Hello from thread 3 of 4 with printf() 
Hello from thread 0 of 4 with printf() 
Hello from thread 2 of 4 with printf() 
Hello from thread 1 of 4 with printf() 
*** outside of parallel region *** 
Hello from thread Hello from thread Hello from thread Hello from thread 1 of 4 with std::cout23 of 4 with std::cout 
of 4 with std::cout 
0 of 4 with std::cout 

~/tmp$ 

あなたは慎重に見ると、あなたが個々のコールのいずれもが見ることができませんstd::cout::operator<<()は分割されていますが、新しい呼び出しが行われるたびに、さまざまなスレッドが互いに競合し、出力を混乱させる機会になります。

また、printf()がアトミックであり、物事を混乱させないということは間違っていますが、単純に複雑な出力文字列の場合は、std::coutよりもマングリングされる可能性が低くなります。