【发布时间】:2014-07-28 22:48:34
【问题描述】:
与许多其他开发人员一样,我对 Apple 的新 Swift 语言感到非常兴奋。 Apple 声称它的速度比 Objective C 更快,并且可以用来编写操作系统。从我目前学到的知识来看,它是一种静态类型语言,能够精确控制确切的数据类型(如整数长度)。所以它看起来确实有很好的潜力处理性能关键任务,比如图像处理,对吧?
这是我在进行快速测试之前的想法。结果真的让我吃惊。
这是一个简单的C语言sn-p代码:
test.c:
#include <stdio.h>
#include <stdint.h>
#include <string.h>
uint8_t pixels[640*480];
uint8_t alpha[640*480];
uint8_t blended[640*480];
void blend(uint8_t* px, uint8_t* al, uint8_t* result, int size)
{
for(int i=0; i<size; i++) {
result[i] = (uint8_t)(((uint16_t)px[i]) *al[i] /255);
}
}
int main(void)
{
memset(pixels, 128, 640*480);
memset(alpha, 128, 640*480);
memset(blended, 255, 640*480);
// Test 10 frames
for(int i=0; i<10; i++) {
blend(pixels, alpha, blended, 640*480);
}
return 0;
}
我在我的 Macbook Air 2011 上使用以下命令编译了它:
clang -O3 test.c -o test
10帧处理时间约为0.01s。也就是说,C 代码处理一帧需要 1ms:
$ time ./test
real 0m0.010s
user 0m0.006s
sys 0m0.003s
然后我有相同代码的 Swift 版本:
test.swift:
let pixels = UInt8[](count: 640*480, repeatedValue: 128)
let alpha = UInt8[](count: 640*480, repeatedValue: 128)
let blended = UInt8[](count: 640*480, repeatedValue: 255)
func blend(px: UInt8[], al: UInt8[], result: UInt8[], size: Int)
{
for(var i=0; i<size; i++) {
var b = (UInt16)(px[i]) * (UInt16)(al[i])
result[i] = (UInt8)(b/255)
}
}
for i in 0..10 {
blend(pixels, alpha, blended, 640*480)
}
构建命令行是:
xcrun swift -O3 test.swift -o test
在这里,我使用相同的O3 级别优化标志来使比较希望公平。但是,结果速度慢了 100 倍:
$ time ./test
real 0m1.172s
user 0m1.146s
sys 0m0.006s
换句话说,Swift 大约需要 120 毫秒来处理一帧,而 C 只需要 1 毫秒。
发生了什么?
更新:我正在使用 clang:
$ gcc -v
Configured with: --prefix=/Applications/Xcode6-Beta.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 6.0 (clang-600.0.34.4) (based on LLVM 3.5svn)
Target: x86_64-apple-darwin13.2.0
Thread model: posix
更新:不同运行迭代的更多结果:
以下是不同“帧”数的结果,即将主 for 循环数从 10 更改为其他数字。请注意,现在我的 C 代码时间变得更快(缓存热?),而 Swift 时间并没有太大变化:
C Time (s) Swift Time (s)
1 frame: 0.005 0.130
10 frames(*): 0.006 1.196
20 frames: 0.008 2.397
100 frames: 0.024 11.668
更新:`-Ofast` 有帮助
使用@mweathers 建议的-Ofast,Swift 速度上升到合理范围。
在我的笔记本电脑上,带有-Ofast 的 Swift 版本在 10 帧和 100 帧中获得 0.013 秒和 0.048 秒,接近 C 性能的一半。
【问题讨论】:
-
出于好奇,将混合计算替换为
var b = (UInt16)(px[i]) &* (UInt16)(al[i])是否有帮助,如果我正确阅读文档将导致 swift 避免溢出检查? -
如果您将代码调整为两次执行相同的过程(即,将迭代从 10 次扩展到 20 次)会发生什么?我想启动 Swift 运行时的成本比启动 C 运行时要高一些。
-
你能转储汇编代码吗?我的猜测是 clang 版本可能正在优化除以常数 255
-
尝试仅分析
blend函数。填充数组和环境设置的差异可能在起作用。 -
阅读整个链接,可以看到“将 Swift 编译器 - Xcode 中的优化级别更改为 'Fastest, Unchecked' 加快了这一速度以与您的 C++ 相媲美。”
标签: c macos performance swift