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;
        }
    }
});
Était-ce utile?

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.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top