CPU 上的并行八叉树构造
Parallel octree construction on the CPU
我做了一个八叉树的简单实现。现在我正在尝试在 CPU.
上并行构建树
首先,我尝试使向树的子节点添加点的步骤平行(这是构造中成本最高的步骤),但由于每次添加时都必须锁定 vector/list指出它没有获得任何性能优势。
现在我正在尝试并行构建树中的每个节点。这个想法很简单,应该是直截了当的,因为节点之间没有交集。我只需要为每个线程分配一个节点来处理。问题是它是一个嵌套的自上而下的实现,所以我不确定什么是最好的实现方式。
我正在使用 C++ 和 OpenMP。我试着在构建函数中写这个:
omp_set_nested(1);
#pragma omp parallel for schedule(dynamic)
for (int i = 0; i < child_count; i++) {
_child[i]->build(threshold, maximumDepth, currentDepth + 1);
}
但是性能变得比连续的差很多。
然后我尝试只并行化前 8 个节点(根节点)。这使我获得了 X2-X3 的性能增益。但是,这在很大程度上取决于场景。如果我的场景太不平衡,那么并行性将没有什么好处,因为前 8 个节点中的 7 个可能几乎是空的,而一个节点拥有所有其他点。
对如何正确执行此操作有任何想法吗?
使用任务而不是嵌套并行。试试这个代码:
#pragma omp parallel
#pragma omp single nowait
{
\ first call to build function
}
内部构建函数使用以下代码。请注意,currentDepth> XXX
是停止创建更多任务的条件。
for (int i = 0; i < child_count; i++)
{
#pragma omp task final( currentDepth> XXX ) mergeable \
default(none) firstprivate(threshold, maximumDepth, currentDepth)
_child[i]->build(threshold, maximumDepth, currentDepth + 1);
}
如果 child_count > 1 下面的代码可能会更快:
for (int i = 0; i < child_count-1; i++)
{
#pragma omp task final( currentDepth> XXX ) mergeable \
default(none) firstprivate(threshold, maximumDepth, currentDepth)
_child[i]->build(threshold, maximumDepth, currentDepth + 1);
}
_child[child_count-1]->build(threshold, maximumDepth, currentDepth + 1);
我做了一个八叉树的简单实现。现在我正在尝试在 CPU.
上并行构建树首先,我尝试使向树的子节点添加点的步骤平行(这是构造中成本最高的步骤),但由于每次添加时都必须锁定 vector/list指出它没有获得任何性能优势。
现在我正在尝试并行构建树中的每个节点。这个想法很简单,应该是直截了当的,因为节点之间没有交集。我只需要为每个线程分配一个节点来处理。问题是它是一个嵌套的自上而下的实现,所以我不确定什么是最好的实现方式。
我正在使用 C++ 和 OpenMP。我试着在构建函数中写这个:
omp_set_nested(1);
#pragma omp parallel for schedule(dynamic)
for (int i = 0; i < child_count; i++) {
_child[i]->build(threshold, maximumDepth, currentDepth + 1);
}
但是性能变得比连续的差很多。
然后我尝试只并行化前 8 个节点(根节点)。这使我获得了 X2-X3 的性能增益。但是,这在很大程度上取决于场景。如果我的场景太不平衡,那么并行性将没有什么好处,因为前 8 个节点中的 7 个可能几乎是空的,而一个节点拥有所有其他点。
对如何正确执行此操作有任何想法吗?
使用任务而不是嵌套并行。试试这个代码:
#pragma omp parallel
#pragma omp single nowait
{
\ first call to build function
}
内部构建函数使用以下代码。请注意,currentDepth> XXX
是停止创建更多任务的条件。
for (int i = 0; i < child_count; i++)
{
#pragma omp task final( currentDepth> XXX ) mergeable \
default(none) firstprivate(threshold, maximumDepth, currentDepth)
_child[i]->build(threshold, maximumDepth, currentDepth + 1);
}
如果 child_count > 1 下面的代码可能会更快:
for (int i = 0; i < child_count-1; i++)
{
#pragma omp task final( currentDepth> XXX ) mergeable \
default(none) firstprivate(threshold, maximumDepth, currentDepth)
_child[i]->build(threshold, maximumDepth, currentDepth + 1);
}
_child[child_count-1]->build(threshold, maximumDepth, currentDepth + 1);