索引与指针

问题描述 投票:3回答:2

我正在使用元素数组,其中许多元素相互引用,我假设在这种情况下使用指针更有效。但在某些情况下,我需要知道我有指针的元素的索引。例如,我有p = &a[i],我需要知道i的价值。据我了解,i可以通过p - a计算。但是这种操作固有地涉及分割,这是昂贵的,而从数组索引计算地址涉及乘法并且更快。

所以我的问题是,在需要索引的情况下是否使用指针进行交叉引用甚至是值得的?

c performance pointers
2个回答
10
投票

但是这种操作固有地涉及分割,这是昂贵的,而从数组索引计算地址涉及乘法并且更快。

仅当元素的大小不是2的幂时,即当它不是指针时,或者在大多数系统上的某种标准类型时,该操作才需要除法。使用比特移位除以2的幂,这是非常便宜的。

从数组索引计算地址涉及乘法并且更快。

这里适用相同的逻辑,除了编译器向左移动而不是向右移位。

在需要索引的情况下,使用指针进行交叉引用甚至是值得的吗?

在没有分析的情况下计算CPU周期是过早优化的一个例子 - 在开始设计时要考虑的一件坏事。

更重要的考虑因素是索引更加健壮,因为它们经常在数组重新分配后继续存在。

考虑一个例子:假设有一个数组在向后添加元素时动态增长,该数组的索引和指向该数组的指针。你向数组添加一个元素,耗尽它的容量,所以它现在必须增长。你调用realloc,得到一个新的数组(如果在“官方”结束后有足够的额外内存,则获得一个旧数组)。你持有的指针现在无效;但是,索引仍然有效。


3
投票

索引数组是非常便宜的,因为我从来没有通过直接使用指针来发现任何性能提升。这包括一些非常关键的性能区域,例如循环遍历包含数百万个图像的图像的每个像素 - 在索引和指针之间仍然没有可测量的性能差异(尽管如果您可以使用两个顺序循环访问图像,它确实会有所不同)。

我实际上发现了许多相反的情况,在需要存储大量数据时,64位硬件开始变得可用后,将指针转换为32位索引可提高性能。

其中一个原因是显而易见的:现在可以使用32位索引占用一半的空间(假设您不需要超过约43亿个元素)。如果你正在存储一大堆它们并占用内存的一半,就像索引网格这样的图形数据结构一样,那么当你的链接/邻接数据可以存储在内存空间的一半时,通常你会得到更少的缓存未命中。

但在更深层次上,使用索引可以提供更多选择。 realloc指出,你可以使用纯粹连续的结构,使dasblinkenlight成为新的尺寸,而不必担心失效。索引也往往更密集(相对于整个64位寻址空间中的稀疏碎片),即使你在数组中留下空洞,允许有效压缩(delta,参考帧等),如果你想压缩内存使用量。然后,您还可以使用并行数组将数据并行关联,而无需使用像哈希表那样昂贵的东西。这包括并行位集,允许您在线性时间内设置交叉点。它还允许SoA代表(也是并行阵列),这对于使用SIMD的顺序访问模式而言往往是最佳的。

你可以通过索引获得更多的优化空间,如果你在指数之上保持指针,我认为这主要是浪费内存。指数的缺点主要是方便。我们必须能够访问我们在索引本身之上索引的数组,而指针允许您访问该元素而无需访问其容器。编写围绕索引的代码和数据结构通常更加困难且容易出错,并且因为我们无法通过索引看到元素的值而更难以调试。也就是说,如果你接受额外的负担,那么通常你会有更多的空间来优化指数,而不是更少。

© www.soinside.com 2019 - 2024. All rights reserved.