2016-11-23 13 views
1

私は並列システムを非並列システムに対してテストしたいという問題があります。並列C++でのメモリの設定

は、システム1では、私は、次のようなメモリを確立:

std::vector<double>* p_val_vec_main = new std::vector<double>(*mpStages); 
std::vector<double>* p_val_vec_slave = new std::vector<double>(*mpStages-1); 
std::vector<std::vector<double> >* p_mat_cache = 
    new std::vector<std::vector<double> >(3, std::vector<double>()); 

これらのベクターは、周りに渡され、したがって、ポインタと新しい構文を繰り返し、RAIIシステムで使用されています。私が行く初めて参照するが

#pragma omp parallel 
{ 
    std::vector<double>* p_val_vec_main = new std::vector<double>(*mpStages); 
    std::vector<double>* p_val_vec_slave = new std::vector<double>(*mpStages-1); 
    std::vector<std::vector<double> >* p_mat_cache = 
    new std::vector<std::vector<double> >(3, std::vector<double>()); 
} 

:のようなオーバーラップ - 推測 - システム2(並列システム)において

、私は何がある与えられていない並列に3つのベクトルを確立しようとしていますプラグマブロックの外側が、プラグマブロックは、私は、エラーコードを受け取るシステム2における有効な要素で、あるメソッド内で「p_val_vec_main」:これが起こった理由を誰もが知っていた場合

error: 'p_val_vec_main' was not declared in this scope 

は思っていましたか?これが何であるかという私の唯一の考えは、おそらくローカル/グローバルな衝突であろう。

+0

あなたがシステム2の「基準p_val_vec_main」と言うとき、あなたは文字通りあなたの 'プラグマOMPのparallel'ブロック内の宣言された変数を参照してください意味ですか?または、RAIIシステムに「渡された」ポインタのコピーを参照しているとしますか? – Edward

+0

プラグマブロックの外側ですが、プラグマブロックが@Edwardのメソッドの場合 – mwtmurphy

+0

'new std :: vector <...'はほとんど常に悪い考えです。実際にはすべてのコンテナに適用されます。コンテナタイプは直接使用してください。"Using RAII"はポインタの引数ではなく、ポインタの引数です。 – MSalters

答えて

0

コンパイラエラーにより問題が明確に説明されています。ブロック内で宣言されたp_val_vec_main

#pragma omp parallel 
{ 
    std::vector<double>* p_val_vec_main = new std::vector<double>(*mpStages); 
    // Other declarations skipped 
} 

このブロックからはアクセスできません。 Block scope hereについてもっと読む。

+0

私はスコープについて理解していますが、私の疑問はなぜ並列スコープでこれを行うのかということです。さらに、他の宣言をスキップする理由は何ですか? – mwtmurphy

+0

@ Murphy'sLaw '#pragma omp parallel'は並列に実行されるべき領域を定義します。このスコープは他のブロックスコープと同じ可視性ルールを持ちます。したがって、あなたの他のロジックがこのスコープの外にある場合、そこで定義された変数にアクセスすることはできません。 – Nikita

+0

@ Murphy'sLawそれが役に立ったのですか、もっと助けが必要でしたか?これまたは他の回答があなたの質問を解決した場合は、チェックマークをクリックしてupvotingおよび/または[accepting](http://meta.stackexchange.com/q/5234/179419)を検討してください。 – Nikita

1

システム2でのみ使用する#pragma omp parallelブロックは、ポインタ変数p_val_vec_main(およびその他の変数)を隠す追加のスコープレベル(開始ブレーク記号とクロージングブレーク記号の間に)を作成します。その前と後のステートメントこれは、parallelブロック内のステートメントを内部的に関数に変換するので、ブロック内で宣言された変数はすべて関数ローカルになるため、omp parallelを使用するために必要な部分です。

あなたはomp parallelブロック内のベクトルを初期化しますが、それ以外でそれらを使用したい場合、あなたはこのように、より高いレベルのスコープでポインタを宣言する必要があります:

std::vector<double>* p_val_vec_main; 
std::vector<double>* p_val_vec_slave; 
std::vector<std::vector<double> >* p_mat_cache; 
#pragma omp parallel 
{ 
    p_val_vec_main = new std::vector<double>(*mpStages); 
    p_val_vec_slave = new std::vector<double>(*mpStages-1); 
    p_mat_cache = 
    new std::vector<std::vector<double> >(3, std::vector<double>()); 
} 
//p_val_vec_main can be used here 
0

は、技術的な答えを見つけることがGCCは内部的に、関数を作成し、関連するコードをその関数に移動することで、そのブロック内で宣言されたすべての変数がその関数のローカル変数になるようにします(したがって各スレッドへのローカル)。

ICCは、一方で、フォークに似た機構()を使用し、魔法の機能を作成できません。

どちらの実装ももちろん有効であり、意味的に同一です。撮影

http://bisqwit.iki.fi/story/howto/openmp/#ExampleInitializingATableInParallelMultipleThreads