C语言中计算有效的三维数组

时间:2020-03-05 18:56:57  来源:igfitidea点击:

我正在尝试从数字上解三维的一组偏微分方程组。在每个等式中,一个点中未知数的下一个值取决于最近点中每个未知数的当前值。

为了编写高效的代码,我需要在(一维)内存空间中保持三个维度上的点接近,以便每个值仅从内存中调用一次。

我当时在考虑使用八叉树,但我想知道是否有人知道更好的方法。

解决方案

回答

八叉树是要走的路。我们将数组细分为8个八分圆:

1 2
3 4

---

5 6
7 8

然后按照上述顺序将它们按1、2、3、4、5、6、7、8的顺序放置在内存中。我们可以在每个八分圆内递归地重复此操作,直到达到基本大小(大约128个字节左右)为止(这只是一个猜测-请确保通过分析确定最佳截止点)。与朴素的布局相比,它具有更好得多的缓存一致性和引用的局部性。

回答

《多维和度量数据结构基础》一书可确定哪种数据结构是范围查询最快的:八叉树,kd树,R树,...
它还描述了将内存中的各个点保持在一起的数据布局。

回答

一种替代树方法的方法:使用Morton-Order对数据进行编码。

在三维中,它是这样的:取坐标分量并将每个位交织为两个零位。此处显示为二进制:11111b变为1001001001b

一个C函数可以做到这一点(为清楚起见,仅显示11位):

int morton3 (int a)
{
  int result = 0;
  int i;
  for (i=0; i<11; i++)
  {
     // check if the i'th bit is set.
     int bit = a&(1<<i);
     if (bit)
     {
       // if so set the 3*i'th bit in the result:
       result |= 1<<(i*3);
     }
  }
  return result;
}

我们可以使用此功能来合并职位,如下所示:

index = morton3 (position.x) + 
        morton3 (position.y)*2 +
        morton3 (position.z)*4;

这会将三维索引变成一维索引。最好的部分:在3D空间中接近的值在1D空间中也接近。如果我们经常访问彼此接近的值,则由于缓存位置方面的morton顺序编码是最佳的,因此也会获得非常好的加速。

对于morton3,最好不要使用上面的代码。使用一张小桌子一次查找4或者8位,并将它们组合在一起。

希望能帮助到你,
尼尔斯