5

モンテカルロアルゴリズムを実行する簡単なプログラムがあります。アルゴリズムを使用した 1 回の反復には副作用がないため、複数のスレッドで実行できるはずです。したがって、これは私のプログラム全体の関連部分であり、C++11 で記述されています。

void task(unsigned int max_iter, std::vector<unsigned int> *results, std::vector<unsigned int>::iterator iterator) {
    for (unsigned int n = 0; n < max_iter; ++n) {
        nume::Album album(535);
        unsigned int steps = album.fill_up();
        *iterator = steps;
        ++iterator;
    }
}

void aufgabe2() {
    std::cout << "\nAufgabe 2\n";

    unsigned int max_iter = 10000;

    unsigned int thread_count = 4;

    std::vector<std::thread> threads(thread_count);
    std::vector<unsigned int> results(max_iter);

    std::cout << "Computing with " << thread_count << " threads" << std::endl;

    int i = 0;
    for (std::thread &thread: threads) {
        std::vector<unsigned int>::iterator start = results.begin() + max_iter/thread_count * i;
        thread = std::thread(task, max_iter/thread_count, &results, start);
        i++;
    }

    for (std::thread &thread: threads) {
        thread.join();
    }

    std::ofstream out;
    out.open("out-2a.csv");
    for (unsigned int count: results) {
        out << count << std::endl;
    }
    out.close();

    std::cout << "Siehe Plot" << std::endl;
}

不可解なことは、追加するスレッドが増えるほど遅くなることです。4 つのスレッドを使用すると、次のようになります。

real    0m5.691s
user    0m3.784s
sys     0m10.844s

一方、単一のスレッドの場合:

real    0m1.145s
user    0m0.816s
sys     0m0.320s

CPU コア間でデータを移動するとオーバーヘッドが増える可能性があることvectorは認識していますが、起動時に宣言する必要があり、途中で変更しないでください。複数のコアでこれが遅くなる特定の理由はありますか?

私のシステムは i5-2550M で、4 つのコア (2 + ハイパースレッディング) があり、g++ (Ubuntu/Linaro 4.7.3-1ubuntu1) 4.7.3 を使用しています。

アップデート

スレッドを使用しない (1) と、多くのユーザー負荷がかかりますが、スレッドを使用すると (2)、ユーザー負荷よりも多くのカーネルが発生することがわかりました。

10,000 回の実行:

http://wstaw.org/m/2013/05/08/stats3.png

100K 実行:

http://wstaw.org/m/2013/05/08/Auswahl_001.png

現時点のmain.cpp

100K 実行すると、次の結果が得られます。

スレッドがまったくありません:

real    0m28.705s
user    0m28.468s
sys     0m0.112s

プログラムの各部分のスレッド。これらの部分は同じメモリを使用することさえないため、同じコンテナーの同時実行も同様に実行する必要があります。しかし、もっと時間がかかります:

real    2m50.609s
user    2m45.664s
sys     4m35.772s

そのため、3 つの主要部分で CPU の 300% を使用していますが、6 倍の時間がかかります。

1Mランで、real 4m45やるのに時間がかかりました。real 20m私は以前に 1M を実行しましたが、少なくともreal 30m.

4

2 に答える 2

5

GitHub で現在の main.cpp を評価しました。上記のコメントに加えて:

  1. はい、rand() はスレッドセーフではないため、マルチスレッド ビジネス ロジックを実行する前に、いくつかの配列にランダムな値を事前に入力しておく価値があります (そうすれば、可能なロックの量を減らすことができます)。ヒープ アクティビティを実行する予定がある場合のメモリ割り当てについても同様です (マルチスレッドの前に事前割り当てを行うか、スレッドごとのカスタム アロケータを使用します)。
  2. 他のプロセスを忘れないでください。4 つのコアで 4 つのスレッドを使用する場合、CPU リソースを他のソフトウェア (少なくとも OS ルーチン) と競合することになります。
  3. ファイル出力は、大きなロッカー プレーヤーです。ループの反復ごとに「<<」演算子を使用すると、多くのコストがかかります (過去に 1 つの面白いケースを覚えています。ログ出力を実行すると、1 つのマルチスレッドのバグが間接的に修正されました。汎用ロガーはロック駆動であるため、ある種の同期プリミティブ、注意してください!)。
  4. 最後に、マルチスレッド アプリがシングル スレッドよりも高速であるという保証はありません。CPU固有、環境固有などの側面がたくさんあります。
于 2013-05-10T12:35:54.777 に答える