Jel*_*pen 5 c++ arrays parallel-processing gpgpu c++-amp
我在 C++ AMP 中处理大型数组(超过 65536 个元素)时遇到问题。我正在使用 C++ amp 来计算多边形列表的法线、切线和双切线向量。输入由位置数组(每个位置 3 个浮点数)和 uv 坐标数组(每个顶点 2 个浮点数)组成。在我的parallel_for_each函数中,我计算法线、切线和双切线(每组3个顶点各1个)。我将它们写回数组(封装在 array_view 中)。该算法如下所示:
concurrency::extent<2> ePositions(positionsVector.size() / 3, 3);
concurrency::array_view<const float, 2> positions(ePositions, positionsVector);
concurrency::extent<2> eUVs(uvsVector.size() / 2, 2);
concurrency::array_view<const float, 2> UVs(eUVs, uvsVector);
concurrency::extent<2> eNormalDirections(normalDirectionsVector.size() / 3, 3);
concurrency::array_view<float, 2> normalDirections(eNormalDirections, normalDirectionsVector);
normalDirections.discard_data();
concurrency::extent<2> eTangentDirections(tangentDirectionsVector.size() / 3, 3);
concurrency::array_view<float, 2> tangentDirections(eTangentDirections, tangentDirectionsVector);
tangentDirections.discard_data();
concurrency::extent<2> eBitangentDirections(bitangentDirectionsVector.size() / 3, 3);
concurrency::array_view<float, 2> bitangentDirections(eBitangentDirections, bitangentDirectionsVector);
bitangentDirections.discard_data();
concurrency::parallel_for_each(eNormalDirections.tile<1, 3>(), [=](concurrency::tiled_index<1, 3> t_idx) restrict(amp)
{
< ... calculate the normals, tangents and bitangents and write them back ... >
}
normalDirections.synchronize();
tangentDirections.synchronize();
bitangentDirections.synchronize();
Run Code Online (Sandbox Code Playgroud)
原始数据包含在PositionsVector和uvsVector中。输出存储在normalDirectionsVector、tangentDirectionsVector和bitangentDirectionsVector中。三个位置(以及相关的紫外线对)形成一个多边形。由于每个多边形只需要一个法线、切线和双切线,因此输出向量的大小比输入向量的大小小三倍。所有向量都封装在第一个代码块中的 array_view 中。
只要要计算的法线数量小于 65536,该算法就可以正常工作。一旦我需要 65536 或更多法线,就会出现以下异常:
concurrency::parallel_for_each (tiling):不支持的计算域,计算域的维度 0 的范围 (65536) 超出了独占限制 (65536)
由于我想要处理的几何图形由超过 65536 个多边形组成,因此这个限制对我来说是一个问题。我无法想象 C++ AMP 仅限于处理少于 65536 个元素。因此,我想知道我的方法犯了什么错误,以及如何处理超过 65536 个元素的数组。
大多数 GPU 至少有 1 GB 的全局内存,array并且array_view都将数据存储在全局内存中。在这种情况下,array_view它会自动与主机 (CPU) 内存中的数据同步。他们也有tile_static更有限的内存。在这种情况下,我不相信您会遇到任何与内存相关的限制。
计算域extent传递给parallel_for_each并描述了 GPU 上正在使用的线程数。GPU 只能执行有限数量的总线程。这是错误消息中描述的您已达到的限制。改变计算域的维数并不能解决您的问题,无论线程的排列方式如何,问题都是线程总数。这是 GPU 硬件的一般限制(您也会发现 CUDA 的类似限制)。
您有几种方法可以解决此问题。
1) 您可以将计算分解为小于总线程限制的块。这可能还有一个额外的好处,即允许您使用前一个块的计算隐藏复制开销。
2) 让计算域中的每个线程计算多个多边形的结果。这将允许您增加每个线程完成的工作量,如果它实际上受到数据传输的限制,这可能会提高整个算法的效率。
3) 1 & 2 的组合。