我面临的问题是分割大型数据集(高达 2048x2048x40x10000 x,y,z,t == 解压后的几 TB,给予或接受)。从好的方面来说,这个数据集中的特征相当小。最大 20x20x20x20 左右。
据我所知,没有开箱即用的解决方案(如果我错了,请纠正我)。我有一些如何解决这个问题的计划,但我希望得到您的反馈。
一个时间片最大约为 600mb;在典型情况下较少;我可以在我的 4gb 内存中保存一堆连续的此类切片。
鉴于我的特征尺寸很小,我的直觉告诉我最好避开所有形式的分割技巧,而只需对我的标签进行局部迭代的类似洪水填充的更新;如果你的邻居有更高的标签,复制它;迭代直到收敛。迭代次数应受任何维度中的最大集群大小的限制,这又应该很小。
CUDA 天生偏爱 3D,所以我可以分两步进行;迭代所有尚未收敛的 3d 体积切片。然后简单地对所有连续的时间片进行元素循环,并执行相同的填充逻辑。
我可以用一个简单的递增唯一计数器来初始化迭代,或者先找到局部最大值,然后在那里种子标签。后者是首选,所以我可以保留一个按标签索引的数组来存储所有区域的 x、y、z、t 最小/最大范围(也可以作为后处理)。如果一个区域没有扩展到最新的时间片,它会从数据中删除,并将其位置写入数据库。如果尾随时间片以这种方式完全耗尽(总和为零),请将其从内存中删除。(或者如果内存溢出,也删除最新的;必须忍受这样的近似值)
看起来应该可以。考虑到 z 维度的大小有限,您认为是启动 x,y,z 线程块,还是启动 x,y 块并让每个线程在 z 维度上循环更好?这是一种“试试看”的事情,还是有一个答案?
我刚刚想到的另一个优化;如果我将一个 x,y,z 块加载到共享内存中,那么在我获得内存的同时执行几次洪水填充更新会不会更快?也许最好让本地内存迭代到收敛,然后继续……我想这与上述问题有关。单个邻居最大查找可能是次优的计算强度,因此在 z 上循环或迭代多次应该可以抵消这一点。我觉得我更喜欢后者。
另一个问题; 似乎不存在类似的东西,但是包含执行类似操作的模板代码的项目的链接将受到高度赞赏(优化的 3d 洪水填充代码?),因为我的 CUDA 知识仍然参差不齐。
提前感谢您的想法和反馈!