C ++结构:成员越多,成员访问时间越慢?

时间:2010-09-24 10:39:53

标签: c++

我有一个结构链表。假设我将x百万个节点插入到链表中, 然后我遍历所有节点以找到给定的值。

奇怪的是(对我来说至少),如果我有这样的结构:

struct node
    {
    int a;
    node *nxt;
    };

然后,我可以通过列表进行迭代,并检查比我在结构中有另一个成员的速度快十倍的值,如下所示:

struct node_complex
   {
   int a;
   string b;
   node_complex *nxt;
   };

我也用C样式字符串(char数组)尝试过,结果是一样的: 因为我有另一个成员(字符串),整个迭代(+值检查)慢了10倍 ,即使我甚至没有碰过那个会员!现在,我不知道结构的内部是如何工作的,但它看起来要付出很高的代价......

有什么收获?

修改: 我是初学者,这是我第一次使用指针,所以很有可能,错误就在于我。我会尽快发布代码(现在不在家)。

更新: 我再次检查了这些值,我知道看到的差异要小得多:2倍而不是10倍。 这肯定是更合理的。

虽然昨天肯定也是如此,昨晚我感到非常疲惫,我不能分两个数字,我刚做了更多测试,结果令人心碎。

相同数量的节点的时间是:

  1. 一个int和一个指针,迭代槽的时间是0.101
  2. 一个int和一个字符串:0.196
  3. 一个int和2个字符串:0.274
  4. 一个int和3个字符串:0.147(!!!)
  5. 对于两个整数,它是:0.107
  6. 看看结构中有两个以上的字符串会发生什么!它变快了!有人把LSD放进我的咖啡里吗?没有!我不喝咖啡。

    对于我的大脑来说,这太过分了,所以我想我会自己解决这个问题,而不是在SO处耗尽公共资源。

    (广告:我认为我的剖析课没有错误,无论如何我能用自己的眼睛看到时差)。

    无论如何,谢谢你的帮助。 欢呼声。

5 个答案:

答案 0 :(得分:7)

我必须与内存访问有关。你说的是一百万个相关元素。在节点中只有一个int和一个指针,它需要8个字节(假设32位指针)。这占用8 MB内存,大约是缓存大小的大小。

添加其他成员时,会增加数据的整体大小。它不再完全适合缓存内存。您恢复到速度慢得多的普通内存访问。

答案 1 :(得分:5)

这也可能是因为在迭代期间您可能创建结构的副本。那就是:

node* pHead;
// ...

for (node* p = pHead; p; p = p->nxt)
{
    node myNode = *p; // here you create a copy!
    // ...
}

快速复制简单结构。但是您添加的成员是string,这是一个复杂的对象。复制它是一个相对复杂的操作,具有堆访问权限。

答案 2 :(得分:3)

最有可能的问题是,较大的结构不再适合单个缓存行。

我记得,主流CPU通常使用32字节的缓存行。这意味着数据一次以32字节的块的形式读入高速缓存,如果超过这32个字节,则需要再次进行内存提取。

查看你的结构,它以int开头,占4个字节(通常),然后std::string(我假设,即使没有指定命名空间),这在我的标准库实现(来自VS2010)占用28个字节,总共为32个字节。这意味着初始intnext指针将放置在不同的缓存行中,使用两倍的缓存空间,如果在迭代期间访问这两个成员,则需要两倍的内存访问。 / p>

如果指针被访问,这应该没有区别,因为只需要从内存中检索第二个缓存行。

如果您始终访问int和指针,并且不太经常需要字符串,则重新排序成员可能有所帮助:

struct node_complex
{
   int a;
   node_complex *nxt;
   string b;
};

在这种情况下,next指针和int位于相同的缓存行上,彼此相邻,因此可以在不需要额外内存读取的情况下读取它们。但是,一旦您需要阅读string,就会产生额外费用。

当然,您的基准测试代码也可能包括创建节点,或者创建节点的(有意或无意)副本,这显然也会影响性能。

答案 3 :(得分:1)

我根本不是一个空间主义者,但在阅读你的问题时,“缓存未命中”问题在我脑海中浮现。

如果你有一个成员,因为它会使结构的大小变大,它也可能会在链接列表中缓存未命中(如果你没有在一个集团中分配节点,这自然是缓存不友好的在记忆中彼此相距不远。)

我找不到另一种解释。

但是,我们没有提供创建和循环,所以如果您不仅仅是拥有不能以有效方式执行列表探索的代码,那么仍然很难猜测。

答案 4 :(得分:0)

也许解决方案是指向对象的链接列表。它可能会使事情变得更复杂(除非您使用智能指针等,但可能会增加搜索时间。