Maison > développement back-end > Golang > Qu'est-ce qui cause la perte de performances 4x de Go sur ce microbenchmark d'accès aux baies (par rapport à GCC) ?

Qu'est-ce qui cause la perte de performances 4x de Go sur ce microbenchmark d'accès aux baies (par rapport à GCC) ?

WBOY
Libérer: 2024-02-10 08:51:09
avant
636 Les gens l'ont consulté

在这个数组访问微基准测试中(相对于 GCC),Go 的性能损失了 4 倍,是什么原因造成的?

Dans ce microbenchmark d'accès aux baies (par rapport à GCC), Go subit une perte de performances 4x. Qu'est-ce qui cause cela ? Ce problème implique de nombreux aspects tels que le mécanisme d'exécution et l'optimisation du compilateur du langage Go. Tout d'abord, le langage Go utilise un mécanisme de vérification des limites lors de l'accès aux tableaux, c'est-à-dire que des vérifications des limites sont effectuées à chaque accès à un élément du tableau, ce qui entraînera une certaine perte de performances. Deuxièmement, le compilateur du langage Go est relativement faible en termes d'optimisation et ne peut pas bien optimiser l'accès aux tableaux. De plus, le mécanisme de garbage collection du langage Go aura également un certain impact sur les performances. Pris ensemble, ces facteurs se sont combinés pour que Go subisse une perte de performances 4x dans le microbenchmark d’accès aux baies.

Contenu de la question

J'ai écrit ce microbenchmark pour mieux comprendre les caractéristiques de performance de Go afin de pouvoir faire des choix éclairés quant au moment de l'utiliser.

Du point de vue des performances, je pense que ce serait un scénario idéal pour aller :

  • Aucune allocation/gratuit dans la boucle
  • L'accès au tableau est évidemment dans les limites (la vérification des limites peut être supprimée)

Néanmoins, j'ai constaté une différence de vitesse 4x par rapport à gcc -o3 sur amd64. pourquoi donc?

(Utilisez le timing du shell. Cela prend quelques secondes à chaque fois, le démarrage est donc négligeable)

package main

import "fmt"

func main() {
    fmt.println("started");

    var n int32 = 1024 * 32

    a := make([]int32, n, n)
    b := make([]int32, n, n)

    var it, i, j int32

    for i = 0; i < n; i++ {
        a[i] =  i
        b[i] = -i
    }

    var r int32 = 10
    var sum int32 = 0

    for it = 0; it < r; it++ {
        for i = 0; i < n; i++ {
            for j = 0; j < n; j++ {
                sum += (a[i] + b[j]) * (it + 1)
            }
        }
    }
    fmt.printf("n = %d, r = %d, sum = %d\n", n, r, sum)
}
Copier après la connexion

Version c :

#include <stdio.h>
#include <stdlib.h>


int main() {
    printf("started\n");

    int32_t n = 1024 * 32;

    int32_t* a = malloc(sizeof(int32_t) * n);
    int32_t* b = malloc(sizeof(int32_t) * n);

    for(int32_t i = 0; i < n; ++i) {
        a[i] =  i;
        b[i] = -i;
    }

    int32_t r = 10;
    int32_t sum = 0;

    for(int32_t it = 0; it < r; ++it) {
        for(int32_t i = 0; i < n; ++i) {
            for(int32_t j = 0; j < n; ++j) {
                sum += (a[i] + b[j]) * (it + 1);
            }
        }
    }
    printf("n = %d, r = %d, sum = %d\n", n, r, sum);

    free(a);
    free(b);
}
Copier après la connexion

Mise à jour :

  • Utilisé comme recommandé range peut augmenter la vitesse de déplacement de 2 fois.
  • Par contre, lors de mes tests, -march=native 将 c 速度提高了 2 倍。 (并且-mno-sse给出编译错误,显然与-o3n'est pas compatible)
  • gccgo ressemble ici à gcc (et ne nécessite pas range)

Solution

Regardez la sortie assembleur du programme C et du programme Go. Au moins sur les versions Go et GCC que j'ai utilisées (respectivement 1.19.6 et 12.2.0), la différence la plus directe et la plus évidente est que GCC. Vectoriser automatiquement les programmes C, ce que le compilateur Go semble incapable de faire.

Cela explique également pourquoi vous constateriez une quadruple augmentation des performances, puisque GCC utilise SSE au lieu d'AVX lorsqu'il ne cible pas une architecture spécifique, ce qui signifie que les instructions scalaires 32 bits sont quatre fois plus larges sur lesquelles fonctionner. En fait, l'ajout de -march=native m'a permis d'améliorer les performances de 2 fois car GCC a généré du code AVX sur mon processeur.

Je ne connais pas assez Go pour vous dire si le compilateur Go est intrinsèquement incapable de vectoriser automatiquement, ou si c'est juste ce programme particulier qui le provoque pour une raison quelconque, mais cela semble être la cause première

.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:stackoverflow.com
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal