c++ - 重新排序矢量数据的有效方法(解释为 3D 数组)
问题描述
我正在开发一个用 C++ 编写的应用程序,它必须处理存储在连续内存空间中的一些数据,这些数据被解释为 3D 数组。为了高效的数据处理,我必须改变内存中的数据顺序。
所以这里有一个例子:原始数据位于内存中,我可以通过数据指针 ( ) 访问数据,该数据指针 ( ) 被解释为 3D数组uint16_t*
并具有以下维度
xSize=4, ySize=4, zSize=3
:,y,z )
d_ 0,0,0 | d_ 1,0,0 | d_ 2,0,0 | d_ 3,0,0 | d_ 0,1,0 | d_ 1,1,0 | d_ 2,1,0 | d_ 3,1,0 | .... | d_ 3,0,2 | d_ 3,1,2 | d_ 3,2,2 | d_ 3,3,2 |
现在我想按 z,y,x 的顺序获取数据:
d_ 0,0,0 | d_ 0,0,1 | d_ 0,0,2 | d_ 0,1,0 | d_ 0,1,1 | d_ 0,1,2 | .... | d_ 2,3,2 | d_ 3,3,0 | d_ 3,3,1 | d_ 3,3,2 |
我用以下循环做了一个实现:
for (uint32_t z = 0; z < zSize; z++) {
for (uint32_t y = 0; y < ySize; y++) {
for (uint32_t x = 0; x < xSize; x++) {
uint32_t readPos = z * xSize * ySize + y * xSize + x;
uint32_t outPos = y * xSize * zSize + x * zSize + z;
*(dataOutPtr + outPos) = *(dataInPtr + readPos);
}
}
}
有谁知道如何加快这个算法?是否可以在并发执行中执行某些部分,或者是否有人知道重新排序 3D 数据的另一种解决方案?
解决方案
这必然是一个野蛮的算法。您的循环在源中具有良好的缓存局部性,或者在目标中具有良好的缓存局部性,但不是两者兼而有之。具有讽刺意味的是,这可能也是您重新排列数据的原因,以便在使用时获得更合适的缓存位置,但在您真正完成之前,重新排列原始布局会减慢您的速度。
显然,您必须访问每个元素,并且您最内层的循环体的性能与将要获得的性能差不多。
可能有可能并行化这一点——其他人将不得不探索这一点,因为我在那里没有相关知识——但从基本的 C++ 角度来看,我认为你已经在尽你所能。至少,除非您可以预处理或修复源数据,或者除非您可以完全不进行重新排列(例如,如果您实际上不关心缓存位置,因此可以简单地将索引方案更改为外观)。
推荐阅读
- annotations - SAP FIORI 工具 - 通过 XML UI 本地注释生成的过滤器,需要显示清除按钮
- azure - Azure WVD 主机池 - 显示“无可用”的虚拟网络
- grpc - gRPC 异步服务器是多线程的吗?
- javascript - 当键不存在时,localStorage.getItem() 不返回 null
- reactjs - 如何在反应钩子中获取自定义属性的值?
- python - 修改循环理解的值
- unity3d - 为什么导入后处理包后后处理卷不存在?
- c# - 查看/修改不同 WPF 程序的 VisualTree
- c# - 如何在特定时间和特定队列中安排 Hangfire 后台作业?
- firebase - FLutter 文件初始化失败