【问题标题】:C++ AMP fixed length recursion and tree traversalC++ AMP 固定长度递归和树遍历
【发布时间】:2016-02-09 19:12:14
【问题描述】:

使用 C++ AMP 我需要遍历最大深度为 10 的四叉树。我知道 C++ AMP 不支持递归,因为它不需要设备有堆栈,但我希望它是能够推出一个小的有限递归深度调用树,因此它仍然可以在没有堆栈的情况下内联和处理。

喜欢

int recur(int i) restrict(amp) {
    if (i <= 1) return 1;
    else if (i > 5) return 1000; //just dummy code to limit the depth
    else return i + recur(i - 1);
}

看来运气不好。不递归规则真的没有例外吗?

关于这个问题,我想知道使用 C++ AMP 遍历树的常用方法是什么。显然,我可以创建自己的每个线程堆栈,然后在深入之前推送当前节点,然后在返回的路上弹出,或者我可以扩展我的树以将“指针”保持在树上,不仅向下,而且...... .

找不到任何显示 C++ AMP 树遍历的示例,我想知道这里的最佳做法是什么?

编辑:我这样做是为了在 2D 域中查找邻居。我有 n 个随机定位的点,需要为每个点找到最近的邻居。这些点位于按空间填充曲线 (https://en.wikipedia.org/wiki/Z-order_curve) 排序的单个 1D 数组中,因此 1D 数组中接近的点在 2D 中也趋于接近,这反过来意味着它们倾向于共享许多邻居也是一样的。

【问题讨论】:

  • “树”在 GPU 代码的上下文中并不常见。 GPU 在历史上的分支预测很差,当您使用这种数据结构时,这确实会降低性能。首先执行所有代码,然后确定应该执行哪个分支是很常见的!也许使用“array-as-a-a-fixed-depth-tree”可能是有意义的。参见algoviz.org/OpenDSA/Books/OpenDSA/html/CompleteTree.html 此外,递归代码可以用迭代表示:参见programmers.stackexchange.com/questions/24997/…
  • 感谢您的评论。您是正确的,如果不加以防范,树可能会导致发散,这对 gpu 来说是非常糟糕的。对于邻居搜索,沿着空间填充曲线对数据进行排序不会阻止这种情况,但会大大缓解这个问题。我将编辑我的问题以保存实际的使用场景,因为这是相关的。我的 cpu 版本的节点已经在一个平面数组中,我确实考虑过使用我自己的堆栈结构进行迭代遍历。我主要想知道“最好的”GPU 实现。
  • 邻居查找是什么意思...对于 n 个点,为每个点查找最近的邻居?所以输入是(p1,p2,p3...),输出是点对(pa,pb)(pc,pd),...?你需要为每个点找到多少个邻居?
  • 我需要在一定的搜索范围内找到所有的。

标签: recursion tree c++-amp


【解决方案1】:

尽管这个问题已经过时,但我想提供一些建议,这些建议不仅适用于 C++ AMP,而且适用于所有尝试执行最近邻查询的 GPGPU 应用程序。

有几种方法可以规避在 GPU 内核中使用堆栈。我使用的一种方法(在 OpenCL 中)是使用所谓的历史标志。该方法在a GDC presentation called Parallelizing the Physics Pipeline 中进行了描述。
这个想法是在树的每一层存储 4 位。每 4 位明确编码下一个需要访问的节点。不幸的是,历史标志所需的大小太大而无法放入线程专用内存中,您必须将它们放在tile_static 内存中,您必须注意银行冲突。

根据我的经验,执行半径搜索会带来一些在 GPU 上无法有效解决的问题。首先,由于您正在执行半径搜索,因此您不知道单个点会有多少个邻居,但您必须预先提供空间来保存相应的点。最后,您将得到一个搜索半径有限的 kNN 搜索。根据您要解决的问题,这可能已经成为交易破坏者。
由于您需要找到最近的点,因此您必须以某种方式对最近的邻居候选者进行排序,这些候选者最终会形成某种堆结构。此时线程发散将减少任何性能增益(除了点是均匀分布的)。

【讨论】:

    【解决方案2】:

    如果您知道最大递归深度,则可以使用模板让编译器将您的递归展开到最大深度:

    template <int I>
    int recur(int i) restrict(amp) {
        if (i <= 1) return 1;
        else if (i > 5) return 1000; //just dummy code to limit the depth
        else return i + recur<I-1>(i - 1);
    }
    
    template<>
    int recur<0>(int i) restrict(amp)
    { // maximum depth reached...
        return 1000;
    }   
    
    void f() restrict(amp)
    {
        recur<10 /* maximum depth */>(3);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-07-12
      • 2014-03-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多