索引与指针

时间:2016-09-09 17:55:57

标签: c performance pointers

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

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

2 个答案:

答案 0 :(得分:10)

  

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

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

  

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

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

  

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

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

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

考虑一个例子:让我们假设你有一个数组,当你向后面添加元素时,它会动态增长,该数组的索引和指向该数组的指针。你向数组添加一个元素,耗尽它的容量,所以它现在必须增长。你打电话给script,然后得到一个新阵列(如果"官方"结束后有足够的额外内存,则得到一个旧阵列)。你持有的指针现在无效;但是,索引仍然有效。

答案 1 :(得分:3)

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

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

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

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

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