尝试使用 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());
. 我正在努力寻找更好的方法。