繁体   English   中英

为什么Apple Accelerate框架有时会很慢?

[英]Why sometimes Apple Accelerate framework is slow?


我正在使用C和Swift 3.0代码,使用来自Apple的vecLib和Accelerate框架作为基于C lang的项目和Swift playground中的动态库+我的代码。

并且与主叫从SIMD指令的框架苹果的包装中包含1或<4个元素运算功能的情况vvcospif()框架是比简单的非标准慢cos(x * PI)时的功能从循环调用邻近1.000倍的例子。

我知道vvcospif()cos()之间的vvcospif() ,我应该使用vvcospif()来表示x * PI

在游乐场中的示例,您只需复制代码并运行它:

import Cocoa
import Accelerate

func cosine_interpolate(alpha: Float, a: Float, b: Float) -> Float {
    let ft: Float = alpha * 3.1415927;
    let f: Float = (1 - cos(ft)) * 0.5;

    return a + f*(b - a);
}

var start: Date = NSDate() as Date

var interp: Float;

for index in 0..<1000 {
   interp = cosine_interpolate(alpha: 0.25, a: 1.0, b: 0.75)
}

var end = NSDate();
var timeInterval: Double = end.timeIntervalSince(start);

print("cosine_interpolate in \(timeInterval) seconds")

func fast_cosine_interpolate(alpha: Float, a: Float, b: Float) -> Float {
    var x: Float = alpha
    var count: Int32 = 1

    var result: Float = 0
    vvcospif(&result, &x, &count)

    let SINSIN_HALF_X: Float = (1 - result) * 0.5;

    return a + SINSIN_HALF_X * (b - a);
}

start = NSDate() as Date

for index in 0..<1000 {
    interp = fast_cosine_interpolate(alpha: 0.25, a: 1.0, b: 0.75)
}

end = NSDate();
timeInterval = end.timeIntervalSince(start);

print("fast_cosine_interpolate in \(timeInterval) seconds")

我的问题是:

为什么vvcospif()在这个例子中很慢?

可能是因为vvcospif()它是Objective-C运行vvcospif()包装器,并且转换数据结构/从Intel SIMD复制内存 - > Objective-C - > Swift运行时慢于小cos()

我也有C代码+的性能问题

#include <Accelerate/Accelerate.h>

vvcospif(resultVector, inputVector, &count);

inputVectorresultVector是带有1或2个元素的小数组或者只是float变量时,并且循环调用~1.000.000次。

cos(x * PI)计算时间接近20 ms。

vvcospif(x)处理一个floatfloat array[2] - 计算时间接近80 ms! 加速在哪里? :)

是的,在Xcode中我使用编译器-O -whole-module-optimization优化与整个模块opt。 启用。

有关示例的更详细讨论,请参阅“Fast Bezier简介(以及尝试Accelerate.framework)”

第一个基本问题是非内联函数调用非常昂贵。 如果您可以在性能关键代码中提供帮助,则不需要函数调用。 在模块中,编译器通常可以为您内联函数,并且可以为您内联部分stdlib。 但是当你开始跨越模块障碍时,Swift通常无法优化呼叫。

SIMD功能的关键在于您以正确的格式设置所有数据,然后只调用一次。 这样,函数调用的成本由您调用的SIMD优化代码组成。

但请记住,您不必调用Accelerate来获得SIMD优化。 编译器完全能够注意到你已经编写了一个循环并将其转换为内联SIMD算法本身(并且它一直这样做)。 因此,对于许多简单的问题,编译器无论如何都会赢。 想一想:如果调用vvcospif计数为1比调用cos更快,那么他们不会以这种方式实现cos吗?

我没有太多地使用你的代码,但是如果你想用Accelerate改进它的性能,你想要考虑如何安排你所有的输入数据,这样你就可以用一个大的N调用vvcospif一次。这很有可能如果循环(因为cos不是微不足道的话)会快得多。

如果您想在实践中获得Accelerate的示例,以及如何组织数据,请参阅PinchText 这段代码是基于最多10次实时动画,通过动画计算满载几千个字形的页面的偏移量(请参阅PinchText.mov了解结果如何)。 特别关注adjustViewPositions:count:forTouchPoint: . 注意count是多大的,并且数据是逐步转换的,没有循环。 即使抛入(非常昂贵的)ObjC方法调用该方法并不重要,因为它只进行了一次。 摆脱循环中的函数调用是性能编程的重要组成部分。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM