58 votes

Pourquoi Swift est 100 fois plus lent que le C dans ce traitement de l'image de test?

Comme beaucoup d'autres développeurs, j'ai été très excité à propos de la nouvelle Swift de la langue d'Apple. Apple a fait sa vitesse est plus rapide que l'Objective-C et peut être utilisé pour écrire le système d'exploitation. Et à partir de ce que j'ai appris jusqu'à présent, c'est un statique tapé de la langue et de pouvoir avoir de contrôler précisément sur le type de données exactes (comme nombre entier de longueur). Donc il ne ressemble ayant un bon potentiel de performance de gestion de tâches critiques, comme le traitement de l'image, à droite?

C'est ce que j'ai pensé, avant j'ai fait un test rapide. Le résultat m'a vraiment surpris.

Voici une très simplifiée de l'image alpha blending extrait de code en 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;
}

J'ai compilé sur mon Macbook Air 2011 avec la commande suivante:

clang -O3 test.c -o test

Le 10 cadre temps de traitement est d'environ 0,01 s. En d'autres termes, il prend le code C 1ms pour traiter une image:

$ time ./test
real    0m0.010s
user    0m0.006s
sys     0m0.003s

Alors j'ai une Swift version du même code:

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)
}

La construction de la ligne de commande est:

xcrun swift -O3 test.swift -o test

J'utilise ici le même O3 niveau d'optimisation de drapeau à faire la comparaison, espérons juste. Cependant, la vitesse résultante est 100 fois plus lent:

$ time ./test

real    0m1.172s
user    0m1.146s
sys     0m0.006s

En d'autres termes, il faut Swift ~120ms à la transformation d'une image qui prend C juste 1 ms.

Ce qui s'est passé?

Mise à jour: je suis en utilisant 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

Mise à jour: plus de résultats avec les différents cours d'exécution itérations:

Voici le résultat pour différents nombre de "cadres", c'est à dire changer le principal for numéro de boucle de 10 pour les autres numéros. Remarque maintenant je suis encore plus vite du code C temps (cache chaud?), tandis que la Swift de temps ne change pas trop:

             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

Mise à jour: `-Ofast` aide

Avec -Ofast suggéré par @mweathers, la Swift de vitesse qui va jusqu'à la fourchette raisonnable.

Sur mon portable le Swift version avec -Ofast obtient 0.013 s pour 10 cadres et 0.048 s pour 100 cadres, près de la moitié de la performance.

25voto

mweathers Points 640

Bâtiment avec:

xcrun swift -Ofast test.swift -o test

Je suis la fois de:

real    0m0.052s
user    0m0.009s
sys 0m0.005s

11voto

gnasher729 Points 5011

Nous allons simplement se concentrer sur la réponse à la question, qui a commencé avec un "Pourquoi": Parce que vous n'avez pas de tourner des optimisations sur, Swift et s'appuie fortement sur l'optimisation de compilateur.

Cela dit, faire du traitement d'image en C est vraiment stupide. C'est ce que vous avez CGImage et amis.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X