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