【问题标题】:Should i use lookup-lists instead of a lot of multiplication?我应该使用查找列表而不是大量乘法吗?
【发布时间】:2012-09-10 06:25:37
【问题描述】:

在我的应用程序中,我有一个非常大的字节数组,它是一个扁平的 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 值(在加载类时填充)创建一个查找表会更快,还是将乘法保留在那里更快?

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

【问题讨论】:

  • 这是 c#,已编辑主帖以显示这一点。
  • 我已经把它作为一个句子取出并添加它作为一个标签。这样做的好处是代码现在很好地格式化为 c#。
  • 谢谢,我没有意识到它会将代码重新格式化为语言规范!此外,多维数组通常被认为是不好的,这些数组中可能有数百万字节。

标签: c# performance comparison multiplication lookup-tables


【解决方案1】:

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

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

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

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

【讨论】:

  • 有任何改进第二个的技巧,或者我会更好地得到它吗? :)
  • @Merlin33069 - 如果您可以强制所有涉及的大小为 2 的幂,那么您可以避免乘法并改用位移位。
  • 谢谢,我查了一下,它的 LOADS 大部分时间都更快,有时速度是一样的,但旧方法永远不会更快。 dl.dropbox.com/u/9690967/speedy.png
【解决方案2】:

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

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

预先计算的数组索引不会给您带来太多好处,因为预先计算的列表会非常大,而且调查它可能不会像做很少的简单数学那样更快。

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

  • 在不安全的部分放置一个紧密的数组循环并使用指针 见Large array arithmetics in C# 或谷歌“矩阵乘法不安全的 c#”
  • Mono 有一个参数可以跳过边界检查。 可能在你的情况下会更快

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

【讨论】:

  • 不幸的是,尺寸是动态的,我确实预先计算了 SizeX*SizeZ,这有点帮助,我不打算预先计算整个列表,只是 x/z 乘法的结果(它将是不超过 2056 个整数结果的数组)。感谢您的宝贵时间。
猜你喜欢
  • 1970-01-01
  • 2014-07-03
  • 2023-03-15
  • 2011-03-02
  • 2010-09-28
  • 1970-01-01
  • 2012-07-25
  • 1970-01-01
相关资源
最近更新 更多