【问题标题】:ANSI C #define VS functionsANSI C #define VS 函数
【发布时间】:2011-12-07 02:50:45
【问题描述】:

我对代码的性能有疑问。 假设我在 C 中有一个结构:

typedef struct _CPoint
{
    float x, y;
} CPoint;

还有一个我使用结构的函数。

float distance(CPoint p1, CPoint p2)
{
    return sqrt(pow((p2.x-p1.x),2)+pow((p2.y-p1.y),2));
}

我想知道用#define 替换这个函数是否是一个聪明的主意,

#define distance(p1, p2)(sqrt(pow((p2.x-p1.x),2)+pow((p2.y-p1.y),2)));

我认为它会更快,因为不会有函数开销,我想知道是否应该对程序中的所有其他函数使用这种方法以提高性能。所以我的问题是:

我应该用#define 替换我的所有函数来提高我的代码的性能吗?

【问题讨论】:

  • 请使用结尾而不是前导下划线:大多数使用前导下划线都违反了 ISO C 标准,并且大写字母后的下划线特别糟糕,因为这是新的 C 语言关键字使用的 ( _Bool, _Complex, _Generic, _Atomic, ...)

标签: c performance inline c-preprocessor ansi-c


【解决方案1】:

我建议使用inline 函数而不是宏。它将为您提供宏的任何可能的性能优势,而不会产生丑陋。 (宏有一些陷阱,这使得它们很难作为函数的一般替代品。特别是,宏 args 每次使用时都会被评估,而函数 args 在每次“调用”之前都会被评估一次。)

inline float distance(CPoint p1, CPoint p2)
{
    float dx = p2.x - p1.x;
    float dy = p2.y - p1.y;
    return sqrt(dx*dx + dy*dy);
}

(注意我也用dx * dx替换了pow(dx, 2)。两者是等价的,乘法更有可能是有效的。一些编译器可能会尝试优化对pow的调用......但猜猜它们是什么替换它。)

【讨论】:

    【解决方案2】:

    Jared 是对的,在这种特定情况下,pow 调用和 sqrt 调用所花费的周期将比 distance 调用所花费的周期多 2 个数量级。

    有时人们认为小代码等于小时间。不是这样。

    【讨论】:

      【解决方案3】:

      如果使用相当成熟的编译器,如果开启优化,它将在汇编级别为您执行此操作。

      对于 gcc,-O3 或(对于“小”函数)甚至 -O2 选项都可以做到这一点。

      有关这方面的详细信息,您可以考虑阅读此处http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html 以获取“-finline*”选项。

      【讨论】:

        【解决方案4】:

        一共有三件事:

        • 像上面的distance 这样的正常功能
        • 内联函数
        • 预处理器宏

        虽然函数可以保证某种类型的安全性,但由于每次函数调用都需要使用堆栈帧,它们也会导致性能损失。内联函数中的代码会在调用站点复制,因此不会支付罚金——但是,您的代码大小会增加。宏不提供类型安全,还涉及文本替换。

        从所有三个中进行选择,我通常会使用内联函数。仅当宏非常短且在这种形式下非常有用时(如 Linux 内核中的 hlist_for_each

        【讨论】:

          【解决方案5】:

          没有。您永远不应该根据感知到的性能差异在宏和函数之间做出决定。您应该根据函数相对于宏的优点来单独评估它。一般选择功能。

          宏有很多隐藏的缺点,可能会咬你一口。举个例子,您在这里对宏的翻译是不正确的(或者至少没有保留原始函数的语义)。宏 distance 的参数每次被评估 2 次。想象一下我打了以下电话

          distance(GetPointA(), GetPointB());
          

          在宏版本中,这实际上会导致 4 次函数调用,因为每个参数都会被计算两次。如果 distance 被保留为函数,它只会导致 3 个函数调用(距离和每个参数)。注意:我在上述计算中忽略了sqrtpow 的影响,因为它们在两个版本中是相同的。

          【讨论】:

            猜你喜欢
            • 2011-06-13
            • 1970-01-01
            • 1970-01-01
            • 2012-06-24
            • 2011-03-06
            • 2013-10-23
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多