并行操作批处理

时间:2011-01-06 08:47:32

标签: c# parallel-processing task-parallel-library

TPL(任务 - 并行 - 库)中是否有内置支持用于批处理操作?

我最近玩了一个例程,使用查找表即音译在字符数组上进行字符替换:

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

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

我可以看到,这可能是平凡的并行化,所以跳入第一个刺,我知道会因为任务太细粒度而表现更差:

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

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

然后我重新设计算法以使用批处理,以便可以将工作分块到不太细粒度的批处理中的不同线程上。这样就可以按预期使用线程,并且接近线性加速。

我确信在TPL中必须有内置的批处理支持。什么是语法,我该如何使用它?

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

更新

在使用@ Oliver的答案并将Parallel.For替换为Parallel.ForEach and a Partitioner后,代码如下:

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

1 个答案:

答案 0 :(得分:19)

为了更好地了解你,你应该得到Patterns for Parallel Programming: Understanding and Applying Parallel Patterns with the .NET Framework 4。这是一个很好的资源,并解释了如何使用TPL的常用方法。

看一下第26页(非常小的循环体)。在那里你会找到这个例子:

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

因此,您正在搜索的缺失部分是System.Concurrent.Collections.Partitioner