web-dev-qa-db-fra.com

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

Comme beaucoup d'autres développeurs, j'ai été très enthousiasmé par le nouveau langage Swift d'Apple. Apple a affirmé que sa vitesse est plus rapide que l'objectif C et peut être utilisée pour écrire le système d'exploitation. Et d'après ce que j'ai appris jusqu'à présent, c'est un langage de type statique et capable d'avoir un contrôle précis sur le type de données exact (comme la longueur entière). Il semble donc avoir un bon potentiel de gestion des tâches critiques de performance, comme le traitement d'image , droite?

C'est ce que je pensais avant de faire un test rapide. Le résultat m'a vraiment surpris.

Voici un simple 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;
}

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

clang -O3 test.c -o test

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

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

Ensuite, j'ai une version Swift 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 ligne de commande de génération est:

xcrun Swift -O3 test.Swift -o test

Ici, j'utilise le même O3 indicateur d'optimisation de niveau pour rendre la comparaison, espérons-le, juste. Cependant, la vitesse résultante est 100 fois plus lente:

$ time ./test

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

En d'autres termes, cela prend Swift ~ 120ms pour traiter une trame qui prend C seulement 1 ms.

Qu'est-il arrivé?

Mise à jour: j'utilise 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 différentes itérations en cours d'exécution:

Voici le résultat pour un nombre différent de "trames", c'est-à-dire changer le numéro de boucle principal for de 10 à d'autres nombres. Notez maintenant que je reçois un temps de code C encore plus rapide (cache chaud?), Tandis que le temps Swift 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ée par @mweathers, la vitesse Swift monte jusqu'à une plage raisonnable.

Sur mon ordinateur portable, la version Swift avec -Ofast obtient 0,013 s pour 10 images et 0,048 s pour 100 images, soit près de la moitié des performances C.

57
Penghe Geng

Construire avec:

xcrun Swift -Ofast test.Swift -o test

Je reçois des moments de:

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

Concentrons-nous simplement sur la réponse à la question, qui a commencé par un "Pourquoi": Parce que vous n'avez pas activé les optimisations, et Swift s'appuie fortement sur l'optimisation du compilateur.

Cela dit, faire du traitement d'image en C est vraiment idiot. C'est pour cela que vous avez CGImage et vos amis.

11
gnasher729