Maison > développement back-end > Golang > le corps du texte

Les programmes Go ralentissent lorsque le nombre de goroutines augmente

WBOY
Libérer: 2024-02-09 22:10:10
avant
1289 Les gens l'ont consulté

当 goroutine 数量增加时,Go 程序会变慢

Lorsque le nombre de goroutines augmente, les programmes Go ralentissent. En effet, la planification et la commutation des goroutines introduiront une surcharge supplémentaire, entraînant une réduction des performances du programme. Bien que les goroutines soient excellentes pour fournir des performances de concurrence, un trop grand nombre de goroutines peut entraîner une concurrence entre les threads et des conflits de ressources, affectant ainsi l'efficacité d'exécution du programme. Afin d'éviter que cette situation ne se produise, nous devons gérer et contrôler raisonnablement le nombre de goroutines pour garantir que le programme peut fonctionner efficacement. Dans cet article, l'éditeur PHP Youzi vous présentera quelques méthodes et techniques d'optimisation des performances des goroutines pour vous aider à améliorer l'efficacité d'exécution des programmes Go.

Contenu de la question

Je travaille sur un petit projet pour mon cours de parallélisme et j'ai essayé d'utiliser des canaux tamponnés, des canaux non tamponnés, des canaux sans utiliser de pointeurs vers des tranches, etc. J'ai également essayé de l'optimiser autant que possible (pas l'état actuel) mais j'obtiens toujours le même résultat : augmenter le nombre de goroutines (même de 1) ralentit tout le programme. Quelqu'un peut-il me dire ce que je fais de mal ? Est-il même possible d’améliorer le parallélisme dans ce cas ?

Ceci fait partie du code :

func main() {

    rand.seed(time.now().unixmicro())

    numagents := 2

    fmt.println("please pick a number of goroutines: ")
    fmt.scanf("%d", &numagents)

    numfiles := 4
    fmt.println("how many files do you want?")
    fmt.scanf("%d", &numfiles)
    start := time.now()

    numassist := numfiles
    channel := make(chan []file, numagents)
    files := make([]file, 0)

    for i := 0; i < numagents; i++ {
        if i == numagents-1 {
            go generatefiles(numassist, channel)
        } else {
            go generatefiles(numfiles/numagents, channel)
            numassist -= numfiles / numagents
        }
    }

    for i := 0; i < numagents; i++ {
        files = append(files, <-channel...)
    }

    elapsed := time.since(start)
    fmt.printf("function took %s\n", elapsed)
}
Copier après la connexion
func generatefiles(numfiles int, channel chan []file) {
    magicnumbersmap := getmap()
    files := make([]file, 0)

    for i := 0; i < numfiles; i++ {
        content := randelementfrommap(&magicnumbersmap)

        length := rand.intn(400) + 100
        hexslice := gethex()

        for j := 0; j < length; j++ {
            content = content + hexslice[rand.intn(len(hexslice))]
        }

        hash := getsha1hash([]byte(content))

        file := file{
            content: content,
            hash:    hash,
        }

        files = append(files, file)
    }

    channel <- files

}
Copier après la connexion

On s'attendait à ce qu'en augmentant le nombre de goroutines, le programme s'exécuterait plus rapidement, mais jusqu'à un certain nombre de goroutines, auquel cas en augmentant le nombre de goroutines, j'obtiendrais le même temps d'exécution ou légèrement plus lent.

EDIT : Toutes les fonctionnalités utilisées :

import (
    "crypto/sha1"
    "encoding/base64"
    "fmt"
    "math/rand"
    "time"
)

type File struct {
    content string
    hash    string
}

func getMap() map[string]string {
    return map[string]string{
        "D4C3B2A1": "Libcap file format",
        "EDABEEDB": "RedHat Package Manager (RPM) package",
        "4C5A4950": "lzip compressed file",
    }
}

func getHex() []string {
    return []string{
        "0", "1", "2", "3", "4", "5",
        "6", "7", "8", "9", "A", "B",
        "C", "D", "E", "F",
    }
}

func randElementFromMap(m *map[string]string) string {
    x := rand.Intn(len(*m))
    for k := range *m {
        if x == 0 {
            return k
        }
        x--
    }
    return "Error"
}

func getSHA1Hash(content []byte) string {
    h := sha1.New()
    h.Write(content)
    return base64.URLEncoding.EncodeToString(h.Sum(nil))
}
Copier après la connexion

Solution

En termes simples, le code de génération de fichiers n'est pas suffisamment complexe pour justifier une exécution parallèle. Tous les changements de contexte et tous les déplacements de données via des canaux consomment tous les avantages du traitement parallèle.

Si vous regardez le contenu de generatefiles 函数的循环中添加类似 time.sleep(time.millisecond * 10) comme s'il s'agissait de quelque chose de plus complexe, vous verrez ce à quoi vous vous attendez : plus de goroutines fonctionnent plus rapidement. Mais encore une fois, ce n’est que jusqu’à un certain point que le travail supplémentaire du traitement parallèle est payant.

A noter également, le temps d'exécution du dernier bit du programme :

for i := 0; i < numAgents; i++ {
    files = append(files, <-channel...)
}
Copier après la connexion

Dépend directement du nombre de goroutines. Étant donné que toutes les goroutines se terminent à peu près au même moment, la boucle s'exécute rarement en parallèle avec vos threads de travail, et le temps nécessaire à son exécution est simplement ajouté au temps total.

Ensuite, lorsque vous ajoutez plusieurs fois à une tranche files, celle-ci doit s'agrandir plusieurs fois et copier les données vers le nouvel emplacement. Vous pouvez éviter cela en créant initialement une tranche qui remplit tous les éléments du résultat (heureusement, vous savez exactement combien d'éléments sont nécessaires).

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!

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