11

マルチコアプログラミングクラスのプロジェクトのコーディングを終えているときに、あなたと話し合いたいと思っていた本当に奇妙なことに気づきました。

マルチコアプラットフォーム向けにプログラムすることで大幅な改善が見られるプログラムを作成するように依頼されました。OpenCLを試すために、GPUで何かをコーディングしてみることにしました。私はマトリックス畳み込み問題に精通しているので、それを選択しました(以前、open_mpiを使用して並列化し、大きな画像を大幅に高速化しました)。

これが、大きなGIFファイル(2.5 MB)[2816X2112]を選択し、シーケンシャルバージョン(元のコード)を実行すると、平均15.3秒になります。

次に、MBP統合GeForce 9400Mで作成したばかりの新しいOpenCLバージョンを実行すると、平均で1.26秒のタイミングが得られます。これまでのところ、12倍のスピードアップです。

しかし、今度は省エネパネルに移動して「グラフィックパフォーマンスモード」をオンにします。このモードでは、GeForce 9400Mがオフになり、システムに搭載されているGeforce9600MGTがオンになります。Appleによれば、このカードは統合されたカードの2倍の速度です。

何だと思いますか、キックアスグラフィックカードを使用したタイミングは平均3.2秒です…私の9600MGTは9400Mより2倍以上遅いようです。

OpenCLに傾倒している方のために、開始する前にすべてのデータをリモートバッファーにコピーするので、実際の計算ではメインRAMへのラウンドトリップは必要ありません。また、OpenCLがそのパラメーターを理解するのにかなり良い実装を行ったことを読んだので、OpenCLに最適なローカルワークサイズを決定させました。

誰か手がかりがありますか?

編集:ここにmakefilesを含む完全なソースコードhttp://www.mathieusavard.info/convolution.zip

cd gimage
make
cd ../clconvolute
make
put a large input.gif in clconvolute and run it to see results
4

5 に答える 5

10

9400M はメモリ コントローラに統合されていますが、9600M GT は PCI-e バス経由でメモリ コントローラに接続されたディスクリート カードです。つまり、メモリを 9400M に転送すると、システム RAM に割り当てられるだけです。一方、9600M は、PCI-e を介してカードの専用グラフィックス メモリにデータを送信します。この転送は、ベンチマークが遅く見える原因です。

2 つのグラフィックス カードのパフォーマンスを比較したい場合は、現在使用しているクロック関数の代わりに OpenCL プロファイリング関数を使用する必要があります。

cl_int clGetEventProfilingInfo (cl_event event, cl_profiling_info param_name, size_t param_value_size, void *param_value, size_t *param_value_size_ret)

カーネルをエンキューするときに作成されたイベントを関数に渡し、2 番目の引数として CL_PROFILING_COMMAND_START を渡してカーネルの開始点をナノ秒単位で取得し、CL_PROFILING_COMMAND_END を渡してカーネルの終了点を取得します。このコマンドは、カーネルの実行が終了した後に必ず使用してください (イベントは、範囲外になるまで値を保持します)。また、この関数をイベントに適用することで、データをデバイスに転送するのにかかった時間を取得することもできます。バッファのエンキューから。次に例を示します。

        TRACE("Invoking the Kernel")
    cl::vector<cl::Event> matMultiplyEvent;
    cl::NDRange gIndex(32,64);
    cl::NDRange lIndex(16,16);

    err = queueList["GPU"]->enqueueNDRangeKernel(
                                                 matrixMultiplicationKernel, 
                                                 NULL, 
                                                 gIndex, 
                                                 lIndex, 
                                                 &bufferEvent,
                                                 matMultiplyEvent);
    checkErr(err, "Invoke Kernel");


    TRACE("Reading device data into array");
    err = queueList["GPU"]->enqueueReadBuffer(thirdBuff, 
                                              CL_TRUE,
                                              0,
                                              (matSize)*sizeof(float),
                                              testC,
                                              &matMultiplyEvent,
                                              bufferEvent);
    checkErr(err, "Read Buffer");
    matMultiplyEvent[0].wait();
    for (int i = 0; i < matSize; i++) {
        if (i%64 == 0) {
            std::cout << "\n";
        }
        std::cout << testC[i] << "\t";
    }
    long transferBackStart = bufferEvent[0].getProfilingInfo<CL_PROFILING_COMMAND_START>();
    long transferBackEnd = bufferEvent[0].getProfilingInfo<CL_PROFILING_COMMAND_END>();
    double transferBackSeconds = 1.0e-9 * (double)(transferBackEnd- transferBackStart);

    long matrixStart = matMultiplyEvent[0].getProfilingInfo<CL_PROFILING_COMMAND_START>();
    long matrixEnd = matMultiplyEvent[0].getProfilingInfo<CL_PROFILING_COMMAND_END>();
    double dSeconds = 1.0e-9 * (double)(matrixEnd - matrixStart);

この例では C++ ラッパーを使用していますが、概念は同じである必要があります。

お役に立てれば。

于 2010-11-29T02:46:41.537 に答える
2

同じ結果が得られますが、その理由はわかりません。私のカーネルでは、ごくわずかなコピーが必要です (すべてのカーネル呼び出しに必要なすべてのデータを提示し、512x512 のイメージのみを返します)。これは raytracer であるため、カーネルの作業はコピーを大幅に上回ります (400+ms から 10ms)。それでも、9600M GT は約 1.5 倍から 2 倍遅いです。

nVidia のリストによると、9600M GT には 32 個の SP が必要です (9400M の 2 倍)。クロックアップも高くなっていると思われます。

ゲームなど、場合によっては 9600M GT の方が速いように見えます。次のリンクを参照してください: http://www.videocardbenchmark.net/video_lookup.php?cpu=GeForce+9600M+GT http://www.videocardbenchmark.net/video_lookup.php?cpu=GeForce+9600M+GT

アルステクニカによると:

さらに、Snow Leopard の実装に関する興味深い情報が初期のテストで明らかになりました。Snow Leopard は、NVIDIA GeForce 9400M チップセットを使用するマシンのデュアル GPU またはオンザフライ GPU スイッチングを有効にしていないようですが (Leopard から引き継がれた制限です)、OS は両方を OpenCL リソースとして同時に使用できるようです。そのため、MacBook Pro で 9600M GT が有効になっている場合でも、アプリケーションで OpenCL コードが検出された場合、Snow Leopard はそのコードを送信して、9400M でほとんど休止状態にある 16 個の GPU コアで処理することができます。ただし、その逆は当てはまりません。9400M のみを有効にして MacBook Pro を実行すると、電力を節約するために 9600M GT が完全にシャットダウンされ、OpenCL リソースとして使用できなくなります。

これは、私たちが見ているものとは逆のようです。また、一度に 1 つのデバイスだけで CL コンテキストを明示的に設定しています。

ars フォーラムには、9600M GT が double もサポートしていないという提案がいくつかあり、この問題を説明しています。この仮説をテストするために、合成ベンチマークを作成しようとするかもしれません。

于 2010-05-19T15:21:28.103 に答える
1

GeForce9400MとGeforce9600MGTの違いはパフォーマンスだけではありません。大きなものは、1つがディスクリートGPUであるということです。これに伴い、多くの違いが生じます。その中で、次のような違いが影響を与える可能性があります。

  • より多くのコマンドをバッチ処理するドライバーの傾向
  • 記憶は均一ではありません。GPUは通常、自身のメモリにのみアクセスし、ドライバはPCI-Eバスを介してメモリを前後に移動します。

私はいくつかが欠けていると確信しています...

ここにあなたが試すことができるたくさんのアイデアがあります:

  • clFinishを呼び出さないでください。メモリの負荷と実行の間にそれを呼び出す方法は、ドライバーに必要以上の作業を強制します。GPUをストールします。
  • コードのプロファイルを作成して、時間がかかっているものを確認します。CLパフォーマンス分析のサポートについてはまだ知りませんが、clFinish呼び出しを使用すると、CPU側を測定するだけで1次の見積もりが得られます。一般に、遅延によるものとスループットによるものを区別するのは難しいことに注意してください。
于 2010-04-13T12:13:45.950 に答える
1

MacBook で OpenCL をテストしていたときに、同じ問題に遭遇しました。これは、GeForce 9400M が Geforce 9600M GT よりもメイン メモリ バンクへのバス速度が高いためだと思います。そのため、Geforce 9600M GT が GeForce 9400M よりもはるかに強力であっても、メモリを GPU にコピーするのに必要な時間が長すぎて、状況でより強力な GPU の利点を確認できません。また、不適切なワーカー グループ サイズが原因である可能性もあります。

また、このサイトは OpenCL の経験に非常に役立つことがわかりました。

http://www.macresearch.org/opencl

于 2010-04-12T13:38:47.980 に答える
0

私は OpenCL を初めて使用するので、少し素朴かもしれませんが、OpenCL コンピューティング デバイスを切り替えるために省エネルギー パネルに入る必要があるとは思えません。コードで OpenCL コンテキストを設定するときにデバイスを選択すると思います。

私の仮説: 1) 最初に統合 GPU を無効にせずにコードを実行すると、OpenCL はディスクリート GPU を計算デバイスとして選択します。コードは (高速) ディスクリート GPU で実行されます。2) 統合 GPU を最初に無効にすると、OS X GUI の実行負荷がディスクリート カードに強制されます。コードを実行すると、ディスクリート GPU で実行されますが、GUI とリソースが競合します。

この回答は、質問が行われてから 11 か月後に行われますが、うまくいけば誰かの役に立つでしょう...

于 2011-03-10T08:24:42.467 に答える