2

まず、私はマルチスレッドについてほとんど知識がなく、このコードを最適化する最善の方法を見つけるのに苦労していますが、マルチスレッドは私が進むべき道のようです。

double
applyFilter(struct Filter *filter, cs1300bmp *input, cs1300bmp *output)
{
    long long cycStart, cycStop;

    cycStart = rdtscll();

    output -> width = input -> width;
    output -> height = input -> height;

    int temp1 = output -> width;
    int temp2 = output -> height;

    int width=temp1-1;
    int height=temp2 -1;
    int getDivisorVar= filter -> getDivisor();  
    int t0, t1, t2, t3, t4, t5, t6, t7, t8, t9;

    int keep0= filter -> get(0,0);
    int keep1= filter -> get(1,0);
    int keep2= filter -> get(2,0);
    int keep3= filter -> get(0,1);
    int keep4= filter -> get(1,1);
    int keep5= filter -> get(2,1);
    int keep6= filter -> get(0,2);
    int keep7= filter -> get(1,2);
    int keep8= filter -> get(2,2);


    //Declare variables before the loop
    int plane, row, col;    

    for (plane=0; plane < 3; plane++) {
        for(row=1; row < height ; row++) {
            for (col=1; col < width; col++) {

                t0 = (input -> color[plane][row - 1][col - 1]) * keep0;
                t1 = (input -> color[plane][row][col - 1]) * keep1;
                t2 = (input -> color[plane][row + 1][col - 1]) * keep2;
                t3 = (input -> color[plane][row - 1][col]) * keep3;
                t4 = (input -> color[plane][row][col]) * keep4;
                t5 = (input -> color[plane][row + 1][col]) * keep5;
                t6 = (input -> color[plane][row - 1][col + 1]) * keep6;
                t7 = (input -> color[plane][row][col + 1]) * keep7;
                t8 = (input -> color[plane][row + 1][col + 1]) * keep8;

                // NEW LINE HERE

                t9 = t0 + t1 + t2 + t3 + t4 + t5 + t6 + t7 + t8;
                t9 = t9 / getDivisorVar;

                if ( t9 < 0 ) {
                    t9 = 0;
                }

                if ( t9  > 255 ) {
                    t9 = 255;
                } 

                output -> color[plane][row][col] = t9;
            } ....

ほとんどの場合、このコードのすべてが必要というわけではありませんが、いくつかのコンテキストが提供されます。したがって、3 つの「for」ループの最初のループは 0 ~ 2 しかないため、下の 2 つの「for」ループをスレッド化して、異なる「プレーン」値に対してすべて同時に実行できる方法があることを望んでいました。これは可能ですか?もしそうなら、それは実際に私のプログラムをより速くしますか?

4

5 に答える 5

4

また、OpenMP についても検討します。これは、プラグマを使用して非常に簡単な方法でスレッド化できる優れたライブラリです。OpenMP は多くのプラットフォームでコンパイル可能です。それをサポートしていることを確認する必要があります。

8 レベルの for ループを持つ一連のコードがあり、非常にうまくスレッド化されています。

于 2013-03-28T19:26:18.833 に答える
2

はい、完全に可能です。この場合、両方のスレッドが異なるデータ セットで動作するため、アクセスの同期 (つまり、競合状態) を気にせずにイベントを終了する必要があります。

これにより、マルチコア マシンでのコードが確実に高速化されます。

クロス プラットフォーム スレッドの実装については、std::thread (c++ 11 で問題ない場合) を参照してください (ターゲット プラットフォームを指定していないため)。または、スレッドサポートライブラリを使用するとさらに良い

threadcount = min(planes, cores) のように、コアの数を検出して適切な数のスレッドを起動し、各ワーカー関数に単一のプレーンのデータ セットへのアクセスを提供することも考えられます。

于 2013-03-28T19:19:47.863 に答える
0

確かに、これをスレッドに分割できるように見えます。おそらく、かなりの速度向上が見られるでしょう。ただし、コンパイラーはすでにループをアンロールし、命令をベクトル化して並列処理を実行しようとしています。特に異なる場所からの読み取りでメモリバスを飽和させている場合は、期待するほどの利益は得られない可能性があります。

考えられるのは、これが 2D グラフィックス操作である場合、システム上のハードウェアを活用し、並列処理が組み込まれている OpenGL などを使用してみてください。

于 2013-03-28T19:24:49.177 に答える
0

スレッド バージョンのコードは、単純な実装よりも遅くなります。スレッド化されたバージョンでは、同期に多くの時間が費やされるためです。また、スレッド化されたバージョンでは、キャッシュのパフォーマンスが低下します。

また、コンパイラによって 3 パスの外側のforループが展開され、並列に実行される可能性が高くなります。

スレッドバージョンを作成してパフォーマンスを比較できます。とにかく役に立つ経験になります。

于 2013-03-28T19:28:55.293 に答える
0

このような状況では、 for ループを自動的にスレッドに変換するコンパイラを使用するよりも悪い結果になる可能性があります。

このようなコードを使用すると、コンパイラは反復間のデータ依存関係があるかどうかを判断できます。そうでない場合は、for ループを複数のスレッドに安全に分割できることを認識し、標準スレッドの同期を最後に行います。通常、このようなコンパイラーは、スレッドを使用することによるオーバーヘッドがそのメリットを上回るかどうかを実行時に判断するコードを挿入できます。

唯一のことは、それを行うコンパイラがありますか? もしそうなら、このような単純でほぼ明白な並列処理のためにスレッドの利点を得る最も簡単な方法です。

私は、Sun の C コンパイラがそれを行っていることを知っています (Sun の C コンパイラは、これを行う最も早い時期の 1 つだと思います。それは、Sun のコンパイラの Solaris バージョンのみにある可能性があります)。Intel のコンパイラもできると思います。私は GCC について疑問を持っています (ただし、その点について訂正していただければ幸いです)。また、Microsoft のコンパイラについてもよくわかりません。

于 2013-03-28T21:35:15.050 に答える