1

在我的应用程序中,我有一个非常大的字节数组,它是一个扁平的 3 维数组,我们使用 3 个嵌套的 for 循环 (x, y, z) 填充数组,然后我们通过一些数学运算得到我们想要的值,最具体地说:

要获取数组中的索引:

return x + z*SizeX + y*SizeX*SizeZ;

并返回 x/y/z 坐标,给定一个索引:

int index = pos;
var y = (ushort) (pos/SizeX/SizeZ);
pos -= y*SizeX*SizeZ;
var z = (ushort) (pos/SizeX);
pos -= z*SizeX;
var x = (ushort) pos;

return new BlockPos(x, y, z, index, this);

首先,我想第二个可以提高效率,我只是不知道该怎么做,任何帮助将不胜感激:P

我的主要问题是,为 y 和 x 值创建一个查找表(在加载类时填充)对我来说会更快,还是将乘法保留在那里更快?

编辑 这个数学在某些情况下被称为很多,所以如果它会更快,即使对于更长的启动它也会产生更好的差异。

4

2 回答 2

5

大多数语言和架构中,乘法将成为一条(或几条)机器指令。虽然这些指令可能相对昂贵,但它们仍然应该比执行查找操作更便宜 - 并且查找操作很可能需要乘法。

例如“定位数组的第 4 个元素”将是

<array base address> + (3 * <array element size>)

考虑到您的伪代码,我建议的唯一优化是执行SizeX*SizeZ一次“常量”操作(例如 ),然后存储这些结果。

于 2012-09-10T06:32:35.473 回答
0

这些可能会加快您的速度;

  • 制作 SizeX、SizeY、SizeZ 常量
  • 预计算 SizeXZ = SizeX * SizeZ 和其他(也作为常量);

预先计算的数组索引不会为您带来太多好处,因为预先计算的列表会非常大,并且由于很少做简单的数学运算,因此查看它可能不会更快。

C# 中的数组操作相对较慢(与其他一些语言相比),因为大多数访问都经过边界检查。有一些方法可以解决这个问题;

  • 在不安全的部分放置一个紧密的数组循环并使用指针请参阅C# 中的大数组算术 或谷歌以获取“矩阵乘法不安全的 c#”
  • Mono 有一个参数可以跳过边界检查。在您的情况下可能会更快

另一个加速可能是安排你的数学循环,使你的数学处理顺序访问大数组。这样,每次访问都受益于数据通常已经被先前的计算提取到 cpu-cache 中的事实。因此,以这样的方式构造 x,y,z 循环,使您得到 index=1、index=2、index=3 等。而不是 index = 0、index= 256、index = 512 等。

于 2012-09-10T08:47:51.083 回答