Pregunta

¿Hay una función de apoyo en el TPL (Task-Parallel-Biblioteca) para operaciones por lotes?

Yo estaba jugando recientemente con una rutina para llevar a cabo la sustitución de caracteres en una matriz de caracteres usando una tabla de búsqueda es decir, transliteración:

for (int i = 0; i < chars.Length; i++)
{
    char replaceChar;

    if (lookup.TryGetValue(chars[i], out replaceChar))
    {
        chars[i] = replaceChar;
    }
}

Me di cuenta de que esto podría ser parallelized trivial, por lo que saltó en un primer intento, que yo sabía que obtienen peores resultados que las tareas fueron demasiado grano fino:

Parallel.For(0, chars.Length, i =>
{
    char replaceChar;

    if (lookup.TryGetValue(chars[i], out replaceChar))
    {
        chars[i] = replaceChar;
    }
});

I a continuación volvió a trabajar el algoritmo para el uso de dosificación de modo que el trabajo podría ser fragmentada en diferentes hilos en menos lotes de grano fino. Este uso que se hace de hilos como se esperaba y me dio un poco de velocidad lineal hasta cerca.

Estoy seguro de que debe haber soporte integrado para la dosificación en el TPL. ¿Cuál es la sintaxis, y cómo lo uso?

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;
        }
    }
});

Actualizar

Después de usar @ respuesta de Oliver y su sustitución Parallel.For con un Parallel.ForEach y una Partitioner el código es como sigue:

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;
        }
    }
});
¿Fue útil?

Solución

Para una mejor conseguir su cabeza alrededor de usted debe conseguir la Patrones de Programación paralela: Comprensión y aplicación de patrones en paralelo con .NET Framework 4 . Es una gran fuente y explica las formas más comunes sobre cómo utilizar el TPL.

Tome un vistazo a la página 26 (cuerpos de bucle muy pequeñas). Allí encontrará este ejemplo:

Parallel.ForEach(Partitioner.Create(from, to), range =>
{
    for (int i = range.Item1; i < range.Item2; i++)
    {
        // ... process i
    }
});

Así que la pieza que falta que usted está buscando es la System.Concurrent.Collections.Partitioner .

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top