减少C Amp中的GPU-CPU数据传输
发布时间:2020-12-16 07:07:53 所属栏目:百科 来源:网络整理
导读:尝试使用C Amp优化我的应用程序时遇到以下问题:数据传输.对我来说,将数据从CPU复制到GPU没有问题(因为我可以在应用程序的初始状态下执行此操作).更糟糕的是,我需要快速访问由C Amp内核计算的结果,因此GPU和CPU之间的瓶颈是一个痛苦.我读到 Windows 8.1下的
尝试使用C Amp优化我的应用程序时遇到以下问题:数据传输.对我来说,将数据从CPU复制到GPU没有问题(因为我可以在应用程序的初始状态下执行此操作).更糟糕的是,我需要快速访问由C Amp内核计算的结果,因此GPU和CPU之间的瓶颈是一个痛苦.我读到
Windows 8.1下的性能提升,但是我使用的是Windows 7,我并不打算改变它.我读到了关于暂存数组但我不知道他们如何帮助解决我的问题.我需要向主机返回一个浮点值,这似乎是最耗时的操作.
float Subset::reduction_cascade(unsigned element_count,concurrency::array<float,1>& a) { static_assert(_tile_count > 0,"Tile count must be positive!"); //static_assert(IS_POWER_OF_2(_tile_size),"Tile size must be a positive integer power of two!"); assert(source.size() <= UINT_MAX); //unsigned element_count = static_cast<unsigned>(source.size()); assert(element_count != 0); // Cannot reduce an empty sequence. unsigned stride = _tile_size * _tile_count * 2; // Reduce tail elements. float tail_sum = 0.f; unsigned tail_length = element_count % stride; // Using arrays as a temporary memory. //concurrency::array<float,1> a(element_count,source.begin()); concurrency::array<float,1> a_partial_result(_tile_count); concurrency::parallel_for_each(concurrency::extent<1>(_tile_count * _tile_size).tile<_tile_size>(),[=,&a,&a_partial_result] (concurrency::tiled_index<_tile_size> tidx) restrict(amp) { // Use tile_static as a scratchpad memory. tile_static float tile_data[_tile_size]; unsigned local_idx = tidx.local[0]; // Reduce data strides of twice the tile size into tile_static memory. unsigned input_idx = (tidx.tile[0] * 2 * _tile_size) + local_idx; tile_data[local_idx] = 0; do { tile_data[local_idx] += a[input_idx] + a[input_idx + _tile_size]; input_idx += stride; } while (input_idx < element_count); tidx.barrier.wait(); // Reduce to the tile result using multiple threads. for (unsigned stride = _tile_size / 2; stride > 0; stride /= 2) { if (local_idx < stride) { tile_data[local_idx] += tile_data[local_idx + stride]; } tidx.barrier.wait(); } // Store the tile result in the global memory. if (local_idx == 0) { a_partial_result[tidx.tile[0]] = tile_data[0]; } }); // Reduce results from all tiles on the CPU. std::vector<float> v_partial_result(_tile_count); copy(a_partial_result,v_partial_result.begin()); return std::accumulate(v_partial_result.begin(),v_partial_result.end(),tail_sum); } 我检查过上面的例子中最耗时的操作是copy(a_partial_result,v_partial_result.begin());.我想找到一个更好的方法. 解决方法
所以我觉得这里还有其他的东西.您是否尝试过运行代码所基于的原始示例?这是
available on CodePlex.
加载样本解决方案并在Release模式下构建Reduction项目,然后在不连接调试器的情况下运行它.你应该看到这样的输出. Running kernels with 16777216 elements,65536 KB of data ... Tile size: 512 Tile count: 128 Using device : NVIDIA GeForce GTX 570 Total : Calc SUCCESS: Overhead 0.03 : 0.00 (ms) SUCCESS: CPU sequential 9.48 : 9.45 (ms) SUCCESS: CPU parallel 5.92 : 5.89 (ms) SUCCESS: C++ AMP simple model 25.34 : 3.19 (ms) SUCCESS: C++ AMP simple model using array_view 62.09 : 20.61 (ms) SUCCESS: C++ AMP simple model optimized 25.24 : 1.81 (ms) SUCCESS: C++ AMP tiled model 29.70 : 7.27 (ms) SUCCESS: C++ AMP tiled model & shared memory 30.40 : 7.56 (ms) SUCCESS: C++ AMP tiled model & minimized divergence 25.21 : 5.77 (ms) SUCCESS: C++ AMP tiled model & no bank conflicts 25.52 : 3.92 (ms) SUCCESS: C++ AMP tiled model & reduced stalled threads 21.25 : 2.03 (ms) SUCCESS: C++ AMP tiled model & unrolling 22.94 : 1.55 (ms) SUCCESS: C++ AMP cascading reduction 20.17 : 0.92 (ms) SUCCESS: C++ AMP cascading reduction & unrolling 24.01 : 1.20 (ms) 请注意,没有任何示例在您编码的时间附近.尽管可以说CPU更快,数据复制时间是这里的一个重要因素. 这是可以预料的.有效使用GPU涉及将诸如还原之类的操作转移到GPU.您需要移动大量计算以弥补复制开销. 你应该考虑的一些事情: >从CodePlex运行样本会发生什么? 一些更有用的信息 >你用的是什么硬件?>您的数据集有多大,包括输入数据和部分结果数组的大小? (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |