4

C++ AMP を使用して行列を計算しようとしています。幅と高さが 3000 x 3000 の配列を使用し、計算手順を 20000 回繰り返します。

    //_height=_width=3000
    extent<2> ext(_height,_width);
    array<int, 2> GPU_main(ext,gpuDevice.default_view);
    array<int, 2> GPU_res(ext,gpuDevice.default_view);
    copy(_main, GPU_main);
    array_view<int,2> main(GPU_main);
    array_view<int,2> res(GPU_res);
    res.discard_data();
    number=20000;
    for(int i=0;i<number;i++)
    {
        parallel_for_each(e,[=](index<2> idx)restrict(amp)
        {
           res(idx)=main(idx)+idx[0];//not depend from calculation type
        }
    array_view<TYPE, 2>  temp=res;
    res=main;
    main=temp;
    }
    copy(main, _main);

計算の前に、行列をホスト メモリから GPU メモリにコピーし、array_view0 から 7 までの , コード行を作成します。

その後、何らかの操作を計算するためのループを開始し、それを 20000 回繰り返します。反復ごとに、parallel_for_eachC++ AMP を使用して計算するループを開始します。

GPU は非常に高速に計算しますが、結果をホストにコピーするとarray _main、この操作に多くの時間がかかることがわかりましたnumber。また、20000 から 2000 に減らすと、コピーの時間も短縮されることがわかりました。

なぜこれが起こるのですか、それは同期の問題ですか?

4

2 に答える 2

5

あなたのコードは(そのままでは)コンパイルされません。以下は、同じ意図を持つと思われる修正バージョンです。計算時間からコピーの時間を分割したい場合、最も簡単なことは、array<>を使用することです。明示的なコピー。

        int _height, _width;
        _height = _width = 3000;
        std::vector<int> _main(_height * _width); // host data.
        concurrency::extent<2> ext(_height, _width);
        // Start timing data copy
        concurrency::array<int, 2> GPU_main(ext /* default accelerator */);
        concurrency::array<int, 2> GPU_res(ext);
        concurrency::array<int, 2> GPU_temp(ext);
        concurrency::copy(begin(_main), end(_main), GPU_main);
        // Finish timing data copy
        int number = 20000;
        // Start timing compute
        for(int i=0; i < number; ++i)
        {
            concurrency::parallel_for_each(ext,
                [=, &GPU_res, &GPU_main](index<2> idx)restrict(amp)
            {
               GPU_res(idx) = GPU_main(idx) + idx[0];
            });
            concurrency::copy(GPU_res, GPU_temp);       // Swap arrays on GPU
            concurrency::copy(GPU_main, GPU_res);
            concurrency::copy(GPU_temp, GPU_main);
        }
        GPU_main.accelerator_view.wait(); // Wait for compute
        // Finish timing compute
        // Start timing data copy
        concurrency::copy(GPU_main, begin(_main));
        // Finish timing data copy

計算を強制的に終了させるためのwait()呼び出しに注意してください。C++AMP コマンドは通常、GPU で作業をキューに入れます。また、明示的に待機するか、wait()を使用するか、それを待機するか、(たとえば) array_viewでsynchronize()を呼び出して暗黙的に待機する場合にのみ、実行が保証されることに注意してください。 > . タイミングの良いアイデアを得るには、(上記のように) 計算とデータのコピーを別々に行う必要があります。ここでいくつかの基本的なタイミング コードを見つけることができます: http://ampbook.codeplex.com/SourceControl/changeset/view/100791#1983676 in Timer.h 同じフォルダーに使用例があります。

でも。コピー時間と計算時間を分割したくない限り、この方法でコードを実際に書くかどうかはわかりません。GPU に純粋に存在するデータにはarray<>を使用し、GPU との間でコピーされるデータにはarray_view<>を使用する方がはるかに簡単です。

これは、以下のコードのようになります。

        int _height, _width;
        _height = _width = 3000;
        std::vector<int> _main(_height * _width); // host data.
        concurrency::extent<2> ext(_height, _width);
        concurrency::array_view<int, 2> _main_av(_main.size(), _main); 
        concurrency::array<int, 2> GPU_res(ext);
        concurrency::array<int, 2> GPU_temp(ext);
        concurrency::copy(begin(_main), end(_main), _main_av);
        int number = 20000;
        // Start timing compute and possibly copy
        for(int i=0; i < number; ++i)
        {
            concurrency::parallel_for_each(ext,
                [=, &GPU_res, &_main_av](index<2> idx)restrict(amp)
            {
               GPU_res(idx) = _main_av(idx) + idx[0];
            });
            concurrency::copy(GPU_res, GPU_temp);  // Swap arrays on GPU
            concurrency::copy(_main_av, GPU_res);
            concurrency::copy(GPU_temp, _main_av);
        }
        _main_av.synchronize();  // Will wait for all work to finish
        // Finish timing compute & copy

これで、GPU でのみ必要なデータは GPU 上にあると宣言され、同期が必要なデータはそのように宣言されます。より明確で少ないコード。

C++ AMP に関する私の本を読むことで、これについて詳しく知ることができます :)

于 2012-12-23T17:30:40.303 に答える
1

タイミングはどのように測りましたか?計算とコピーの正確なタイミングを得るには、コピーを実行する前に、parallel_for_each の後で、accelerator_view を待機する必要があります。C++ AMP プログラムのパフォーマンスを測定するためのヒントについては、次のブログ記事を参照してください。

  1. C++ AMP アルゴリズムのパフォーマンスを測定する方法 (2011)
  2. C++ AMP アルゴリズムのパフォーマンスを測定する方法 (2012)
于 2012-12-18T21:49:22.567 に答える