Fonctionnement en parallèle Batching
-
26-09-2019 - |
Question
Y at-il un support intégré dans le TPL (Task-Parallel-Library) pour les opérations de dosage?
J'ai récemment joué avec une routine pour effectuer le remplacement de caractères sur un tableau de caractères en utilisant une table de correspondance à savoir translittération:
for (int i = 0; i < chars.Length; i++)
{
char replaceChar;
if (lookup.TryGetValue(chars[i], out replaceChar))
{
chars[i] = replaceChar;
}
}
Je pouvais voir que cela pourrait être trivialement parallélisé, donc sauté avec un premier coup de couteau que je connaissais serait de moins bons résultats que les tâches étaient trop à grains fins:
Parallel.For(0, chars.Length, i =>
{
char replaceChar;
if (lookup.TryGetValue(chars[i], out replaceChar))
{
chars[i] = replaceChar;
}
});
Je puis retravaillé l'algorithme à utiliser batching afin que le travail puisse être morcelées sur différents threads par lots moins à grains fins. Cela fait usage de fils comme prévu et je me suis un peu près jusqu'à la vitesse linéaire.
Je suis sûr qu'il doit être intégré à l'appui pour la mise en lots TPL. Quelle est la syntaxe, et comment puis-je utiliser?
const int CharBatch = 100;
int charLen = chars.Length;
Parallel.For(0, ((charLen / CharBatch) + 1), i =>
{
int batchUpper = ((i + 1) * CharBatch);
for (int j = i * CharBatch; j < batchUpper && j < charLen; j++)
{
char replaceChar;
if (lookup.TryGetValue(chars[j], out replaceChar))
{
chars[j] = replaceChar;
}
}
});
Mise à jour
Après avoir utilisé @ la réponse d'Oliver et le remplacement Parallel.For
avec un Parallel.ForEach et Partitioner le code est le suivant:
const int CharBatch = 100;
Parallel.ForEach(Partitioner.Create(0, chars.Length, CharBatch), range =>
{
for (int i = range.Item1; i < range.Item2; i++)
{
char replaceChar;
if (lookup.TryGetValue(chars[i], out replaceChar))
{
chars[i] = replaceChar;
}
}
});
La solution
Pour mieux obtenir autour de votre tête, vous devriez obtenir le Modèles de programmation parallèle: Comprendre et appliquer les modèles parallèles avec le .NET Framework 4 . Il est une grande source et explique les moyens communs sur la façon d'utiliser le TPL.
Jetez un oeil à la page 26 (corps de boucle très petites). Vous y trouverez cet exemple:
Parallel.ForEach(Partitioner.Create(from, to), range =>
{
for (int i = range.Item1; i < range.Item2; i++)
{
// ... process i
}
});
Ainsi, la pièce manquante vous cherchez est le System.Concurrent.Collections.Partitioner
.