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;
}
}
});
答案 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
。