【问题标题】:Is there a speed difference in passing a pointer or a const struct传递指针或 const 结构是否存在速度差异
【发布时间】:2014-09-12 17:11:31
【问题描述】:

在 C 中,结构通常通过指针传递,以防止数据被复制太多。

我想知道,这真的很重要吗?编译器不会阻止不必要的复制吗?

例如,如果我将一个变量标记为 const,编译器是否会将副本优化掉?

例子

struct my_t {
    int a;
    int b[24];
}

int generate_updated_myt(const my_t c) {
    // do something with c
    return 0;
}

int generate_updated_myt(const my_t * c) {
    // do something with *c
    return 0;
}

一般来说,这两者之间会有速度差异吗?

【问题讨论】:

  • 为什么不自己试试呢?将这两件事都做几百万次,然后测量所花费的时间。
  • @Peter Smit - 查看以下链接,看看它是否回答了您的问题 - 链接 1 - stackoverflow.com/questions/212237/… 链接 2 - stackoverflow.com/questions/6313730/…
  • 哦,作为我之前评论的补充,你应该在构建时尝试不同的优化级别。
  • @JoachimPileborg 是个好主意,但这将是一个数据点——可能是一个异常的数据点——也许其他硬件/编译器/操作系统会有完全不同的结果。
  • 如果您倾向于测试,您可以尝试不同大小的结构(16 字节、128 字节、1kb、16kb 等)

标签: c gcc struct


【解决方案1】:

如果我理解正确,您是在问编译器是否可以优化

int generate_updated_myt(const my_t c);

这样对generate_updated_myt() 的调用实际上会传递一个指针,而不是对象的实际副本(即,它的行为方式类似于C++ const&)。

如果对c 的本地副本的访问被实现为对传入对象的引用而不是实际副本,请考虑以下人为设计的示例:

#include <stdio.h>

struct my_t {
    int a;
    int b[24];
};

int foo(void);
int generate_updated_myt(const struct my_t c)
{
    int a = c.a;

    foo();  // if c is really a 'pointer' to the passed in object,
            //     then this call to `foo()` may change the object
            //     c refers to.

    if (a != c.a) {
        puts("how did my private copy of `c.a` get changed?");
    }

    return a;
}

struct my_t g_instance;

int main(void)
{
    generate_updated_myt( g_instance);
    return 0;
}

int foo(void)
{
    int counter = g_instance.a++;

    return counter;
}

这是不允许您建议的优化的原因之一。

这甚至没有考虑到const 很容易被丢弃(即使它可能是糟糕的形式)。

【讨论】:

    【解决方案2】:

    这将取决于调用约定、结构的大小、相关的缓存和 TLB 条目是否已填充以及您正在使用它做什么。一般来说,很难回答,尽管像寄存器重命名这样的微架构特性会尽最大努力缩小差异。

    我能想到的在这种设计决策中遇到的一个很大的不同是,如果 generate_updated_myt 包含某种可能在 c 上运行的可矢量化循环,则将其声明为 const 可能还不够。除非声明像 const my_t * restrict c __attribute__((aligned(64)))

    这样,否则您可能无法获得矢量化输出

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-06
      • 2011-11-13
      • 1970-01-01
      • 2014-12-29
      • 2016-02-18
      相关资源
      最近更新 更多