关于C#:2-power-of-size数据的性能优势?

Performance advantages of powers-of-2 sized data?

如果我有一个三维世界的游戏,而这个世界非常大,所以需要分块,有没有一个主要的,如果有的话,有128字节的块超过,比如150字节的块的性能优势?显然,块中的对象的大小仍然是整数字节。

也就是说,chunks[128][128][128]chunks[150][150][150]chunks[112][112][112]快吗?之后是否还有其他副作用,如过度的内存浪费?是否还有其他需要考虑的因素?

我只是看到把所有的东西都存储在2次幂的变量和数组中是一种惯例,但我不确定是否有什么好处,也不知道是否可以更好地使用100或150这样的人类数字。


另一个答案确实是正确的,即两种大小的数据的力量将受益于使用移位而不是乘法。

然而,双尺寸数据的威力有一个阴暗面。它会在你最不经意的时候击中你。

请参阅以下两个问题/答案:

  • 矩阵乘法:矩阵大小差小,时间差大
  • 为什么元素添加在单独循环中比在组合循环中更快?

当您的数据集是两种能力的时候,它们更可能在内存中超级对齐。(这意味着它们的地址在2的大幂上可能具有相同的模。)

虽然这似乎是可取的,但它们可以导致:

  • 冲突缓存未命中
  • 假混叠暂停(在上面第二个链接中提到)

如果你阅读上面链接的两个问题,你会发现校准会导致超过3倍的减速——这很可能会大大超过你使用轮班而不是乘法所获得的任何好处。

所以对于所有的性能问题,你需要测量,测量,测量…准备好一切可能发生的事情。

你提到你代表的是一个三维空间——这正是那种会展现出两个跨步内存访问能力的情况,这可能会导致速度下降。


它不完全是"更快",而是更好地利用可用内存,因为硬件和操作系统管理的内存单元的大小很可能是2的幂。由于对齐要求,分配小于二次幂的内容通常会导致内存浪费。

如果深入研究分配器和操作系统内存管理器,您将看到它们以两种大小的能力管理所有东西。操作系统通常以页面的形式管理进程的内存,现在页面大小通常为4096字节。因此,如果您想分配一个4000字节的块,操作系统仍然会分配4096字节,剩余的96字节将被浪费。


如果您通过以下方式访问数据:

1
2
chunks[150][150][150]
chucks[x][y][z] = 123;

然后处理器必须进行乘法运算(例如:z+150*(y+150*x))。为了得到地址。

如果使用2的幂常量,那么编译器可以进行一些优化,并使用移位而不是乘法。新的CPU使乘法速度相当快,所以效果是微不足道的。

使用大表会导致很多缓存未命中。所以小桌子可能比大桌子更快,甚至大桌子也有2倍大小的尺寸,而小桌子则不然。


在软件中经常使用二的幂,因为它是计算机使用的基数。

例如,操作系统将以两次幂的块大小分配内存,处理器中的缓存大小为两次幂,地址大小为两次幂等等。

使用两个值的幂的操作也可以得到优化-乘法或除法变成一个简单的位移位。

基本上,确保每件事都使用两种能力可能会提高软件的性能,但通常情况下,编译器和/或操作系统将确保在使用任意大小时以有效的方式使用数据。


它可能更快,可能更慢,也可能是相同的速度。仅仅通过查看代码就很难给出正确的答案。所以答案是:测量,改变代码,再次测量。如果您的代码必须在不同的计算机上运行,请在每台计算机上测量它。

我倾向于假设两个对齐的能力经常会带来严重的问题,并且使用比需要更多的内存对性能没有帮助。使用一小部分内存进行大量的操作,这些内存可以装入某些缓存,然后切换到内存的下一部分,通常会有所帮助。访问连续的内存地址通常会有所帮助。四舍五入以便使用向量运算通常会有所帮助。