如何在GLSL SSBO中自动“分配”内存?

时间:2018-11-10 17:32:02

标签: multithreading opengl glsl gpu mutex

我正在glsl的缓冲区内部构建树结构。

树中的每个节点都有8个整数,这些整数确定数组中该节点的8个子节点的位置。

例如:

tree[0].children = [1,5,3,9,100000,7,100,10]
tree[1].children = [2,3,4,900,8,11,20,13]

潜在的可能结果。

单个线程“分配”内存的方式是。缓冲区有一个全局索引,初始化为0。

当前线程检查当前节点的子节点之一是否为0,如果是,则将索引增加1,并将子节点的值设置为index的先前值。

换句话说:

if(tree[node].children[current_child] == 0) {
     tree[node].children[current_child] = tree_index++;
}

这显然会造成一些糟糕的竞争条件,因为执行上述操作时,子线程的值和索引可能会被其他线程更改。

我对这个问题的解决方案是创建一个忙循环互斥体,以锁定所有试图在一个线程分配子节点时修改该子节点的线程。看起来像这样:

int mrun = 100;
while ((tree[0].children[child] <= 0) && (mrun > 0))
{
    mrun--;
    //If the node wasn't allocated, allocate its memory (which also releases the lock)
    if( (atomicCompSwap( tree[0].children[child] , 0 , -1) == 0 ))
    {
        tree[0].children[child] = int(atomicAdd(t_index, 1));
    }
}

这有效,但有多个警告。首先,while循环可能会运行过多,因此我必须限制其执行的次数,这会导致某些值的丢失(存在多个重复的值,因此多数情况下很好)。这也迫使我浪费计算周期,等待和检查。最后,着色器中的while循环并不完全理想。

我尝试通过以下方法解决此问题:

  atomicCompSwap(tree[0].children[child], 0, atomicAdd(t_index, 1));

但是,这并没有达到预期的效果,这些操作不是同时原子运行的,因此我最终分配错误。

有没有办法可以更有效地进行此分配?也许是多次通过?

0 个答案:

没有答案