0

ボタンのあるウィンドウが 1 つしかない画像処理プログラムを作成しようとしています。フーリエ変換やハイ/ローパスなどの重い処理関数で MPI を使用する必要があります。

私の問題は、このウィンドウが QT で作成されており、別のタスクを呼び出してこれらの重い処理機能を実行できる単一のウィンドウを作成できなかったことです。どうやってやるの?

したがって、明確にするために、私が欲しいのは次のとおりです。

A - 私のプログラムは一度初期化されます。

B - ユーザーが画像を読み込んでフーリエ ボタンをクリックすると、フーリエ計算が開始されます。

C - フーリエ計算の途中で、MPI との並列化を行う必要があります。そこでは、一部を他のプロセスに送信し、フーリエが完了したらすべてをまとめます。

これは可能ですか?私がこれまでに持っているのはコードのシリアル部分で、MPI で遊んでみました。最初の一瞥では、複数のプロセスが複数のウィンドウを実行していました (同時に 5 つの mspaint を開いているなど)。それを修正するために、私はこれを試しました:

if ( pid == 0 )
{   
        QApplication a(argc, argv);

    MainWindow w;
        w.show();

    a.exec();
}

これにより、単一のウィンドウが作成されます。これを行うことで、for ループを並列化しようとしています。

    if ( pid == 0 )
    {
        printf("This is the master task. There are %d tasks in total", nProcs);

        for ( i = 1; i < nProcs; i++ )
        {
            MPI_Send( &complexPixel[i*width/nProcs][0], width*height/nProcs,  MPI_DOUBLE, i, tag, MPI_COMM_WORLD );
                MPI_Send( &H,   width*height, MPI_DOUBLE, i, tag, MPI_COMM_WORLD );
        }
    }
    else
    {
            printf("This is a slave task. PID = %d\n", pid);
            MPI_Recv( &complexPixel, width*height/nProcs, MPI_DOUBLE, 0, tag, MPI_COMM_WORLD, &statusMPI );
            MPI_Recv( &H, width*height,  MPI_DOUBLE, 0, tag, MPI_COMM_WORLD, &statusMPI );
        }
    }

    DoSomeWork();

    if ( pid != 0 )
    {
        MPI_Send( &T, width*height/nProcs, MPI_DOUBLE, 0, tag, MPI_COMM_WORLD );
        printf("Slave work finished.\n");
    }
    else
    {
        for ( i = 1; i < nProcs; i++ )
                MPI_Recv( &T[i*width/nProcs][0], width*height/nProcs, MPI_DOUBLE, i, tag, MPI_COMM_WORLD, &statusMPI );
            printf("Master work finished.\n");
    }

現在、最初の MPI_Send でスタックしています。マスター タスクにウィンドウ全体を実行するように命令したため、それを処理できる唯一のプロセスのようです。

お時間をいただきありがとうございます!これが機能することを願っています!

4

2 に答える 2

0

私の意見では、絶対にやるべきことは、GUI を表示するバイナリと、計算を行うバイナリを完全に分離することです。私は次のことを試してみます。

GUI を実装するプログラムを作成します。このプログラムは、共有メモリを割り当てる (または shm パーティションにファイルを作成する) 必要があります。MPI で計算を実装する 2 つ目のプログラムを作成します。このプログラムのマスター プロセスは、GUI プログラムと同じノードで実行され、同じ共有メモリ (またはファイル) にアクセスする必要があります。他のプロセスは、マスター プロセスから集合通信 ( aMPI_Bcastまたは など) を受け取るまで待機します。MPI_Gather

マスター プロセスは、GUI プログラムがシグナルをトリガーするまで待機します。このシグナルは、ユーザーの入力が収集され、共有バッファー (またはファイル) がいっぱいになるとすぐに発行されます。この時点で、マスタープロセスが集団通信を発行し、MPI による計算が開始されます。

この計算が終了するとすぐに、マスター プロセスは出力を収集し、共有メモリ (またはファイル) を使用してそれを GUI プログラムに返すか、それを出力ファイルに書き込むか、またはそれに対して行う必要があることをすべて実行し、GUI プログラムに次のことを伝えます。計算は別のシグナルを介して行われるか、GUI プログラムがポーリングしている場合は共有メモリを使用して行われます (これは Qt で簡単に実装できます)。

最後に、MPI では OpenMP のように「ループを並列化」することはできないことを覚えておいてください。プロセス全体とこれらの間の通信を設計する必要があります。また、ユーザー インターフェイス (Qt、curses、CLI など) と計算を混在させないようにすることで、2 つの非常に異なるタスクをプログラマーに分離し、それらを異なるコンパイラ フラグでコンパイルすることができます (たとえば、計算をコンパイルしたい場合があります)。一部は -O3 で、GUI は -O2 または -Os で)。

于 2013-06-17T08:39:49.057 に答える