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_view从 0 到 7 的代码行。

之后,我开始一个循环来计算一些操作并重复 20000 次。每次迭代我都会开始一个parallel_for_each循环,使用 C++ 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 < >。为了更好地了解计时,您应该真正分别计时计算和数据副本(如上所示)。您可以在这里找到一些基本的计时代码:http: //ampbook.codeplex.com/SourceControl/changeset/view/100791#1983676 in Timer.h 在同一个文件夹中有一些使用示例。

然而。我不确定我是否真的会以这种方式编写代码,除非我想打破复制和计算时间。将array<>用于纯粹存在于 GPU 上的数据,使用array_view<>用于复制到 GPU 和从 GPU 复制的数据要简单得多。

这看起来像下面的代码。

        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 上,需要同步的数据也被声明为 GPU 上。更清晰,更少的代码。

您可以通过阅读我关于 C++ AMP 的书了解更多信息:)

于 2012-12-23T17:30:40.303 回答
1

你是如何测量时间的?您需要在 parallel_for_each 之后等待加速器视图,然后再进行复制,以便计算和复制的准确时间。您可能需要查看以下博客文章,了解一些衡量 C++ AMP 程序性能的技巧:

  1. 如何衡量 C++ AMP 算法的性能 (2011)
  2. 如何衡量 C++ AMP 算法的性能 (2012)
于 2012-12-18T21:49:22.567 回答