【问题标题】:Why is Objective-C sqrtf() function faster than a function that just returns a value?为什么 Objective-C sqrtf() 函数比只返回值的函数快?
【发布时间】:2014-02-20 00:08:41
【问题描述】:

我在 Objective-C 中有这些功能:

-(void)emptyFunction
{
    NSTimeInterval startTime = [[NSDate date] timeIntervalSinceReferenceDate];

    float b;
    for (int i=0; i<1000000; i++) {
        b = [self returnNr:i];
    }

    NSTimeInterval endTime = [[NSDate date] timeIntervalSinceReferenceDate];

    double elapsedTime = endTime - startTime;
    NSLog(@"1. %f", elapsedTime);
}

-(float)returnNr:(float)number
{
    return number;
}

-(void)sqrtFunction
{
    NSTimeInterval startTime = [[NSDate date] timeIntervalSinceReferenceDate];

    float b;
    for (int i=0; i<1000000; i++) {
        b = sqrtf(i);
    }

    NSTimeInterval endTime = [[NSDate date] timeIntervalSinceReferenceDate];

    double elapsedTime = endTime - startTime;
    NSLog(@"2. %f", elapsedTime);
}

当我以任何顺序调用它们时,它会在控制台中打印以下内容:

2014-01-13 12:23:00.458 RapidTest[443:70b] 1. 0.011970
2014-01-13 12:23:00.446 RapidTest[443:70b] 2. 0.006308

这是怎么回事? sqrtf() 函数如何比只返回值的函数快两倍?我知道 sqrtf() 可以使用汇编语言等处理位,但比返回更快吗?怎么可能?

【问题讨论】:

  • 我猜 sqrt() 函数是 C 级的,更接近系统,它使用寄存器数据类型。
  • 一个区别是 emptyFunctionsqrtFunction 是方法而不是函数,sqrt() 是 C 级函数,就像 AnoopVaidya 所说的那样。方法与NOT函数有很大区别。

标签: objective-c performance sqrt


【解决方案1】:

调用[self returnNr:i] 与简单地调用C 函数不同。相反,您正在向self 发送消息,该消息将被转换为 C 中的等价物:

objc_msgSend(self, @selector(returnNr:), i);

这最终会调用您的 returnNr: 实现,但会涉及一些开销。有关objc_msgSend 中发生的事情的更多详细信息,请参阅objc_msgSend tourLet's build objc_msgSend

[编辑] 另请参阅An Illustrated History of objc_msgSend,它显示了实现如何随时间变化。由于在objc_msgSend 的演变过程中进行了改进/权衡,从 Q 执行代码将导致在不同平台版本上产生不同的结果。

【讨论】:

  • 该死的好答案。将 returnNr 更改为一个简单的 C 函数,它应该比 sqrtFunction 更快。感谢您的深入解释。
【解决方案2】:

你的基准有缺陷。

首先,在这两种情况下,编译器都可以按如下方式优化您的循环:

for (int i=0; i<1000000-1; i++) {
    [self returnNr:i];
}
float b = [self returnNr:i];

分别:

for (int i=0; i<1000000-1; i++) {
    sqrtf(i);
}
float b = sqrtf(i);

那么,如果编译器可以推断出语句sqrtf(i)没有副作用(除了返回一个值),它可以进一步优化如下:

float b = sqrtf(1000000-1);

clang 很可能会应用此优化,尽管它取决于实现。

另请参阅:Do C and C++ optimizers typically know which functions have no side effects?

在 Objective-C 方法调用的情况下,编译器的优化机会要少得多,并且它很可能总是假设方法调用可能有副作用并且必须始终调用。因此,第二个优化可能不会应用于优化的构建。

此外,您测量经过时间的方法还不够准确。您应该使用马赫计时器来获得精确的绝对时间。并且您需要执行一些“运行”并采取最少的运行。

【讨论】:

    【解决方案3】:

    你的 Obj-C 方法

    -(float)returnNr:(float)number
    {
        return number;
    }
    

    先编译成C-function然后执行,sqrtf()是一个C-function。

    因此,与 Objective-C 方法相比,C 函数会更快。

    【讨论】:

      猜你喜欢
      • 2020-02-07
      • 1970-01-01
      • 1970-01-01
      • 2013-11-21
      • 2017-07-16
      • 2020-09-23
      • 1970-01-01
      • 1970-01-01
      • 2014-06-06
      相关资源
      最近更新 更多