与许多其他开发人员一样,我对Apple的新Swift语言感到非常兴奋。 Apple声称它的速度比Objective C快,可以用来编写操作系统。从我到目前为止所学到的,它是一种静态类型语言,能够精确控制确切的数据类型(如整数长度)。所以它看起来像具有良好的潜在处理性能关键任务,如图像处理,对吧?
在我进行快速测试之前,这就是我的想法。结果真的让我感到惊讶。
以下是C:
中的简单代码段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.01秒。换句话说,它需要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~120ms才需要C只需1 ms。
发生了什么事?
$ 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
@mweathers建议-Ofast
,Swift速度上升到合理的范围。
在我的笔记本电脑上,带-Ofast
的Swift版本10帧时为0.013秒,100帧时为0.048秒,接近C性能的一半。
答案 0 :(得分:23)
建筑用:
xcrun swift -Ofast test.swift -o test
我得到的时间是:
real 0m0.052s
user 0m0.009s
sys 0m0.005s
答案 1 :(得分:10)
让我们专注于问题的答案,该问题以“为什么”开头:因为你没有改变优化,Swift在很大程度上依赖于编译器优化。
那就是说,在C中进行图像处理确实很糟糕。这就是你拥有CGImage和朋友的原因。