gpt4 book ai didi

c++ - 主机需要定期访问的OpenCL最佳内存设置是什么?

转载 作者:搜寻专家 更新时间:2023-10-31 02:20:41 25 4
gpt4 key购买 nike

我正在寻找为我的项目设置CL存储器对象的最佳方法,该方法可以进行设备端物理仿真。主机将在大约每16毫秒每帧访问一次缓冲区,以获取更新的数据进行渲染。不幸的是,我无法通过VBO将新数据直接发送到GPU。

缓冲区中的数据由具有3个cl_float4和一个cl_float的结构组成。我还希望主机能够更新缓冲区中的某些结构,这不是逐帧的。

目前,我希望将所有数据分配/存储在GPU上,并在主机需要访问时使用map / unmap。但这带来了两个我可以看到的问题:

  • 仍然需要设备来托管副本以呈现
  • 每当在模拟中添加/删除对象时,都必须重建
  • 缓冲区。否则每个结构必须存在其他验证数据,以检查此对象是否“有效” /有效...

  • 任何建议表示赞赏。如果您需要其他任何信息或代码段,请告诉我。

    谢谢。

    最佳答案

    有效的内存管理算法

    您需要最佳的OpenCL内存设置。我假设您最关心的是高性能,而不是太多的大小开销。
    这意味着您应该在GPU上执行尽可能多的操作。 CPU / GPU之间的同步应最小化。

    内存模型

    现在,我将详细描述这种内存和处理模型的外观。

  • 以最大大小预分配缓冲区,并随时间填充它们。
  • 跟踪缓冲区
  • 中当前有多少个元素
  • 为有效性和您的数据有单独的缓冲区。有效性缓冲区指示每个元素的有效性

  • 添加元素

    可以通过以下原理来添加元素:
  • 有一个带有主机指针的缓冲区,用于输入数据。缓冲区的大小由最大输入元素
  • 决定
  • 接收数据时,将其复制到主机缓冲区中并将其同步到GPU
  • (可选)在GPU上预处理输入数据
  • 在内核中,在全局缓冲区的最后一个元素后面添加输入数据和相应的有效性。输入点为空(也许您只有100个输入点而不是10000个输入点),只需将其标记为无效即可。

  • 这有几个影响:
  • 可以完全并行添加
  • 您只需要将一个小缓冲区(输入数据缓冲区)同步到GPU
  • 添加输入数据时,始终将最大数量的输入元素添加到缓冲区中,但是大多数输入元素将为空/无效。因此,当您频繁添加点
  • 如果渲染步骤不能丢弃无效点,则必须在渲染之前从模型中删除无效点。
    否则,您可以将清理推迟到只需要进行清理的时候,因为模型的大小会变大并有可能溢出。

  • 删除元素

    删除元素应遵循以下原则:
  • 具有确定元素是否无效的内核。如果是这样,只需相应地标记其有效性即可(如果需要,也可以将数据清零或NAN,但这不是必需的)。
  • 拥有一种算法,该算法能够从缓冲区中删除无效元素,并为您提供有关有效数量的信息,
    缓冲区中的连续元素(添加元素时需要该信息)。
    这种算法将要求您使用并行归约进行排序和搜索。

  • 并行排序元素

    对缓冲区(尤其是具有很多元素的缓冲区)进行排序的要求很高。您应该使用可用的实现。

    简单的Bitonic排序:

    如果您不关心最大的性能和简单的代码,这就是您的选择。
  • 可用的实现:https://software.intel.com/en-us/articles/bitonic-sorting
  • 易于集成,只需一个内核。
  • 只能排序4 * 2 ^ n个元素(据我所记得)。
  • 警告:此类不适用于大于十亿(1,000,000,000)的数字。不知道为什么,但是找到那个花了我很多时间。

  • 快速基数排序:

    如果您关心最大的性能并且要分类的元素很多(100万到10亿甚至更多),这是您的选择。
  • 可用的实现:https://github.com/sschaetz/nvidia-opencl-examples/tree/master/OpenCL/src/oclRadixSort
  • 难以集成,服务器内核调用
  • 只能排序2 ^ n个元素(据我所记得)
  • 比Bitonic排序更快,尤其是具有超过一百万个元素的

  • 找出有效元素的数量

    如果对缓冲区进行了排序并且所有无效元素都已删除,则可以简单地并行计算有效值的数量,也可以简单地找到第一个无效元素的第一个索引(这需要使未使用的缓冲区空间无效)。两种方式都会为您提供有效元素的数量

    问题大小与排序大小限制

    要克服仅能对固定数量的元素进行排序所引起的问题,只需填充您知道其排序行为的值即可。
    例:
  • 您想按升序对10,000个整数,其值在0到1千万之间。
  • 您只能对2 ^ n个元素排序

  • 您得到的最接近值是2 ^ 14 = 16384。
  • 有一个缓冲区,可以对2 ^ 14个元素进行排序
  • 用10000个值填充缓冲区以进行排序。
  • 用一个已知的值填充缓冲区的所有剩余值,该值将排在10,000个实际存在的值之后。
    由于您知道自己的值(value)范围(0到1000万),因此可以选择1100万作为填充值(value)。

  • 就地排序问题

    元素的就地分拣和删除很难(但可能)实现。一个更简单的解决方案是确定连续有效元素的索引,然后按该顺序将它们写入新缓冲区,然后交换缓冲区。
    但这需要您交换缓冲区或复制回来,这会浪费性能和空间。选择适合您情况的较小邪恶。

    更多建议
  • 如果您仍然对表演不满意,则仅添加等待事件。但是,这会使您的代码复杂化并可能引入错误(甚至不会造成您的错误-Nvidia卡和OpenCL存在一个令人讨厌的错误,其中不会存储等待事件和内存泄漏-这将缓慢但肯定会导致问题) 。
  • 在过早地将缓冲区同步/映射到CPU时要非常小心,因为此同步调用将强制使用该缓冲区的所有内核完成
  • 如果很少发生添加元素,并且渲染步骤能够丢弃无效的元素,则可以推迟从缓冲区中删除元素,直到真正需要它为止(太多的元素有可能使缓冲区溢出)。
  • 关于c++ - 主机需要定期访问的OpenCL最佳内存设置是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32382292/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com