2016-12-10 7 views
0

大きな配列で同じ機能を実行するプログラムがあります。私は配列を等しいチャンクに分割し、それらをスレッドに渡します。現在、スレッドは関数を実行し、想定されているものを返しますが、各スレッドが実行するのにかかる時間が長いほど、スレッドを追加します。これは並行性の目的を完全に否定します。私はstd::threadstd::asyncの両方で同じ結果を試しました。下の画像では、すべての子スレッドとメインスレッドで処理されるデータ量は同じです(メインスレッドは6ポイント増えます)が、メインスレッドは〜12秒で実行され、子スレッドはスレッド数を〜12それらは非同期に実行されていました。しかし、それらはすべて同時に開始し、各スレッドから出力すると同時に実行されます。これは参加方法と関係がありますか?私は考えることができるすべてを試しました、どんな助け/助言も大いに感謝されます!サンプルコードでmainは、子スレッドが終了するまで関数を実行しません。メインスレッドの実行後にjoinを実行すると、子スレッドが終了するまで実行されません。 3と5のスレッドで実行するとランタイムが表示されます。これらの時間はテストのために縮小されたデータセットにあります。スケーラビリティスレッドランタイムでのC++同時実行の問題

void foo(char* arg1, long arg2, std::promise<std::vector<std::vector<std::vector<std::vector<std::vector<long>>>>>> & ftrV) { 
    std::vector<std::vector<std::vector<std::vector<std::vector<long>>>>> Grid; 

    // does stuff.... 
    // fills in "Grid" 

    ftrV.set_value(Grid); 
} 


int main(){ 

    int thnmb = 3; // # of threads 
    std::vector<long> buffers; // fill in buffers 
    std::vector<char*> pointers; //fill in pointers 

    std::vector<std::promise<std::vector<std::vector<std::vector<std::vector<std::vector<long>>>>>>> PV(thnmb); // vector of promise grids 
    std::vector<std::future<std::vector<std::vector<std::vector<std::vector<std::vector<long>>>>>>> FV(thnmb); // vector of futures grids 
    std::vector<std::thread> th(thnmb); // vector of threads 
    std::vector<std::vector<std::vector<std::vector<std::vector<std::vector<long>>>>>> vt1(thnmb); // vector to store thread grids 

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

    th[i] = std::thread(&foo, pointers[i], buffers[i], std::ref(PV[i])); 
    } 
    for (int i = 0; i < thnmb; i++) { 
    FV[i] = PV[i].get_future(); 
    } 

    for (int i = 0; i < thnmb; i++) { 
    vt1[i] = FV[i].get(); 
    } 

    for (int i = 0; i < thnmb; i++) { 
    th[i].join(); 
    } 

    // main performs same function as foo here 

    // combine data 
    // do other stuff.. 

    return(0); 
} 

run with

run with 3 threads

+0

スクリーンショットを投稿するのではなく、コマンドウィンドウの内容をコピーして質問に貼り付ける必要があります。 – 1201ProgramAlarm

+0

は@ 1201ProgramAlarmを指摘 – JakeG

答えて

1

それはfooが何を知らなくても、決定的な答えを出すのは難しいですが、あなたはおそらく、メモリアクセスの問題に実行しています。 5次元配列にアクセスするたびに5回のメモリ検索が必要となり、一般的なシステムが提供できるものを飽和させるためにメモリアクセスで2〜3スレッドしかかかりません。

mainは、スレッドを作成した後、約束の価値を得る前に、それをfooで実行する必要があります。

fooはおそらくftrV.set_value(std::move(Grid))で終わるので、その配列のコピーを作成する必要はありません。

+0

ありがとう!私はあなたがメモリアクセスの問題について正しいと信じています。昨夜私はそれが偽の共有と関係があるかもしれないと思ったが、各スレッドがアクセスしているベクトルのチャンクは私のマシンのキャッシュラインよりも1000倍だけ離れているので、これがわかりません問題。私は5次元配列を使用しています。なぜなら、私のデータセットをそうしたやり方で考えるのはもっと直感的です(おそらくこのようには見えません)、それを少し変更して2Dベクトルに分解することができます。メモリ参照コスト? – JakeG

+0

5つではなく2つのベクトルにアクセスするために2つのメモリルックアップを行うだけで済むので、フラットな2Dベクトル<ベクトル>型に変更することができます。 – 1201ProgramAlarm

関連する問題