2017-02-17 6 views
0

J'ai deux morceaux de code et il y a 32 cœurs sur mon bureau.pourquoi l'opération atomique est plus rapide en utilisant des threads séparés?

Code A utilise 32 fils de discussion et fait la chose suivante,

1) valeurs à certains endroits aléatoires dans la mémoire 2) ajouter une valeur à atomiquement une variable globale. Le code B utilise 16 threads pour écrire des valeurs dans des emplacements aléatoires et utilise 16 autres threads pour ajouter de manière atomique une valeur à une variable globale. Je me demandais pourquoi le code B est plus rapide en termes de nombre d'opérations atomiques exécutées par seconde pour la variable globale.

Voici le code A

var a uint64 = 0 

const N = 10 * 1024 * 1024 

var data [N]uint64 

func main() { 

    for i := 0; i < 32; i ++ { 
     go func(id int) { 
      source := rand.NewSource(int64(id)) 
      local_rand := rand.New(source) 
      for { 
       atomic.AddUint64(&a, uint64(1)) 
       data[local_rand.Int31n(N)] = uint64(1) 
      } 
     }(i) 

    } 

    var b uint64 = 0 

    for { 
     c := atomic.LoadUint64(&a) 

     fmt.Println(c - b) 
     b = c 
     time.Sleep(time.Second) 
    } 

} 

Voici le code B

var a uint64 = 0 

const N = 10 * 1024 * 1024 

var data [N]uint64 

func main() { 

    for i := 0; i < 16; i ++ { 
     go func(id int) { 
      source := rand.NewSource(int64(id)) 
      local_rand := rand.New(source) 
      for { 
       data[local_rand.Int31n(N)] = uint64(1) 
      } 
     }(i) 

    } 
    for i := 0; i < 16; i++ { 

     go func() { 
      for { 
       atomic.AddUint64(&a, uint64(1)) 
      } 

     }() 
    } 
    var b uint64 = 0 

    for { 
     c := atomic.LoadUint64(&a) 

     fmt.Println(c - b) 
     b = c 
     time.Sleep(time.Second) 
    } 

} 

Répondre

1

Les opérations atomiques sont coûteuses. Afin de maintenir l'atomicité, vous devez assurer une exécution mutuellement exclusive pour ce bloc de code. Habituellement ceci est accompli en utilisant des instructions comme load-linked, store-conditionnel etc. Dans votre code A, vous avez 32 opérations atomiques, mais dans le code B, vous n'avez que 16. Moins de travail atomique, temps d'exécution réduit! En tant qu'expérience, essayez de changer l'ordre des opérations atomiques avec l'opération de mémoire dans votre code A. (Faites juste d'abord la mémoire et atomique ensuite). Vous devriez voir une réduction du temps d'exécution.

+0

Je ne pense pas que changer le nombre de threads à 16 dans le code A améliore les performances. – luyi0619

+0

Je ne vois aucune différence par rapport à ce que vous avez proposé. La mémoire d'abord, puis l'atomique. Ai-je manqué quelque chose? – luyi0619

+0

Si vous avez d'abord tous les threads en mode atomique, ils se disputeront tous pour le verrou. Si vous avez d'abord la mémoire, ils feront tous d'abord de la mémoire, mais en raison de ce qui est en cache ou non, le fonctionnement de la mémoire se terminera à des moments différents. Cela signifie que les opérations atomiques commenceront à des moments différents. Vous n'aurez donc pas le même argument que vous aviez précédemment. Donc je m'attendais à moins de temps d'exécution. Peut-être que toutes vos données sont cachées, ne pas faire ce que je m'attendais ... de toute façon juste une théorie qui m'a traversé l'esprit. –