Beaucoup d'entre nous commenceraient probablement à implémenter quelque chose de manière non parallèle et auraient besoin de refactoriser le code et d'utiliser le parallélisme. Y at-il une théorie ou une suggestion sur la façon de trouver des fonctions de point chaud ou des morceaux de code pour le parallélisme efficace.Comment trouver des points chauds pour le parallélisme dans .net 4?
Par exemple, je peux avoir la pièce de code suivante dans un style non-parallèle:
int[] data = new int[1000000]; // Just a big trunk of data.
// Here is just a procedure on the trunk of data, performing repeated work.
void SequentialProcedure(){
for(int i = 0; i < data.Length; i++) data[i] += rand.Next();
}
Pour un gars comme moi sans beaucoup d'expérience de parallélisme, au premier coup d'œil, il ressemblerait à une fonction peut être appliqué avec une certaine habileté de parallélisme:
int[] data = new int[1000000]; // The same big trunk of data.
// A parallel implementation.
void ParallelProcedure(){
Parallel.ForEach(Partitioner.Create(0, data.Length),
range => {
for(int i = range.Item1; i < range.Item2; i++) data[i] += rand.Next();
}
);
}
OK. Même si je lis quelque chose et que la tâche d'ajouter un nombre aléatoire à chaque élément vectoriel est petite comparée au coût de création des délégués et utilise des plages pour rendre chaque tâche parallèle plus charnue, la version parallèle est encore plus lente que la version séquentielle . À ce stade, je vais me perdre: alors la procédure séquentielle est simplement une fonction qui ne convient pas au parallélisme? ou la façon dont j'essaie de le paralléliser est juste faux? y a-t-il des suggestions, des directives de gourous que nous pouvons suivre en repérant où le parallélisme prendrait plus d'effet et où le parallélisme serait simplement une perte de temps?
Merci beaucoup pour votre aide.
Edit:
Afin de rendre chaque itération plus charnue, ajouter une deuxième itération de niveau. Ainsi, le code séquentiel devient:
int[] data = new int[100];
void SequentialProcedure(){
for(int i = 0; i < data.Length; i++){
for(int j = 0; j < 500000; j++) data[i] = rand.Next(j, Int32.MaxValue);
}
}
Et la version parallèle devient:
int[] data = new int[100];
void ParallelProcedure(){
Parallel.ForEach(Partitioner.Create(0, data.Length),
range => {
for(int i = range.Item1; i < range.Item2; i++){
for(int j = 0; j < 500000; j++) data[i] = rand.Next(j, Int32.MaxValue);
}
}
}
Il est intéressant de voir que même maintenant chaque itération externe a assez de travail à faire, la procédure parallèle est encore presque 4 fois plus lent que la procédure séquentielle sur ma machine.
Est-il possible de résoudre certains problèmes d'allocation/mise en cache?
Éditer: apparemment, il est moins probable qu'un problème de mémoire entraîne le ralentissement du parallèle dans l'exemple ci-dessus. Vraiment besoin de comprendre la raison ...
Ceci ne concerne que la moitié de la question. Il a une fonction qu'il pense devrait paralléliser facilement, mais cela va deux fois plus lentement en utilisant le TPL. Alors pourquoi? – Gabe
Merci Gabe. Pour Domenic, oui, le profil aide à repérer le code lent. Mais la compétence est nécessaire pour "voir avec perspicacité" si les opérations sont parallélisables et comment "voir avec droiture" est ce que je cherche de l'aide. – Steve
Eh bien, j'imagine que la raison pour laquelle la fonction ci-dessus n'est pas bien parallélisée est exactement la raison pour laquelle vous donnez dans votre message: à savoir. "La tâche réelle d'ajouter un nombre aléatoire à chaque élément vectoriel est faible par rapport au coût de création de délégués et d'utiliser des plages pour rendre chaque tâche parallèle plus charnue." Les choses qui ne sont pas lentes ne se parallélisent pas bien. – Domenic