Tim*_*oyd 8 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;
}
}
Run Code Online (Sandbox Code Playgroud)
我可以看到这可能是平凡的并行化,所以跳进了第一次刺,我知道会因为任务太细粒度而表现更差:
Parallel.For(0, chars.Length, i =>
{
char replaceChar;
if (lookup.TryGetValue(chars[i], out replaceChar))
{
chars[i] = replaceChar;
}
});
Run Code Online (Sandbox Code Playgroud)
然后我重新编写算法以使用批处理,这样就可以将工作分成不同细粒度的不同线程.这使得线程按预期使用,并且我得到了一些接近线性的加速.
我确信必须内置支持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;
}
}
});
Run Code Online (Sandbox Code Playgroud)
更新
使用@Oliver的答案并替换Parallel.For为Parallel.ForEach和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;
}
}
});
Run Code Online (Sandbox Code Playgroud)
Oli*_*ver 19
为了更好地了解您的应用,您应该获得并行编程模式:使用.NET Framework理解和应用并行模式4.它是一个很好的来源,并解释了如何使用TPL的常用方法.
看看第26页(非常小的循环体).在那里你会发现这个例子:
Parallel.ForEach(Partitioner.Create(from, to), range =>
{
for (int i = range.Item1; i < range.Item2; i++)
{
// ... process i
}
});
Run Code Online (Sandbox Code Playgroud)
所以你正在搜索的缺失部分是System.Concurrent.Collections.Partitioner.