Parallel.ForEach 和 Regex 没有提高性能吗?

Her*_*r33 0 c# regex parallel-processing multithreading .net-4.0

我有一个程序,它根据结果以某种方式对返回的结果集进行颜色编码。由于对结果进行颜色编码所需的时间较长(目前使用 Regex 和 RichTextBox.Select + .SelectionColor 完成),我在 400 个结果处切断了颜色编码。在这个数字左右,大约需要 20 秒,这大约是我认为合理的最长时间。

为了尝试提高性能,我重写了 Regex 部分以使用循环Parallel.ForEach来迭代MatchCollection,但时间大致相同(18-19 秒 vs 20 秒)!难道这个工作不太适合并行编程吗?我应该尝试一些不同的东西吗?欢迎任何建议。谢谢!

PS:我觉得有点奇怪,无论有没有 Parallel.ForEach,我的 CPU 利用率都没有达到 14% 左右。

代码

MatchCollection startMatches = Regex.Matches(tempRTB.Text, startPattern);

object locker = new object();
System.Threading.Tasks.Parallel.ForEach(startMatches.Cast<Match>(), m =>
{
    int i = 0;
    foreach (Group g in m.Groups)
    {
        if (i > 0 && i < 5 && g.Length > 0)
        {
            tempRTB.Invoke(new Func<bool>(
                delegate
                {
                    lock (locker)
                    {
                        tempRTB.Select(g.Index, g.Length);
                        if ((i & 1) == 0) // Even number
                            tempRTB.SelectionColor = Namespace.Properties.Settings.Default.ValueColor;
                        else              // Odd number
                            tempRTB.SelectionColor = Namespace.Properties.Settings.Default.AttributeColor;
                        return true;
                    }
                }));
        }
        else if (i == 5 && g.Length > 0)
        {
            var result = tempRTB.Invoke(new Func<string>(
                delegate
                {
                    lock (locker)
                    {
                        return tempRTB.Text.Substring(g.Index, g.Length);
                    }
                }));

            MatchCollection subMatches = Regex.Matches((string)result, pattern);

            foreach (Match subMatch in subMatches)
            {
                int j = 0;
                foreach (Group subGroup in subMatch.Groups)
                {
                    if (j > 0 && subGroup.Length > 0)
                    {
                        tempRTB.Invoke(new Func<bool>(
                            delegate
                            {
                                lock (locker)
                                {
                                    tempRTB.Select(g.Index + subGroup.Index, subGroup.Length);
                                    if ((j & 1) == 0) // Even number
                                        tempRTB.SelectionColor = Namespace.Properties.Settings.Default.ValueColor;
                                    else              // Odd number
                                        tempRTB.SelectionColor = Namespace.Properties.Settings.Default.AttributeColor;
                                    return true;
                                }
                            }));
                    }
                    j++;
                }
            }
        }
        i++;
    }
});
Run Code Online (Sandbox Code Playgroud)

Ser*_*rvy 5

事实上,程序的任何方面实际上都无法并行运行。

匹配的生成需要按顺序完成。在找到第一个匹配之前,它无法找到第二个匹配。 Parallel.ForEach最多允许您并行处理序列的结果,但它们仍然是按顺序生成的。这似乎是你大部分耗时工作的所在,而且没有任何收获。

最重要的是,您也没有真正并行处理结果。循环体中运行的大部分代码都在对 UI 线程的调用中,这意味着它们全部由单个线程运行。

简而言之,程序中只有一小部分实际上是并行运行的,并且使用并行化通常会增加一些开销;听起来你几乎没有得到比这个开销更多的东西。您确实没有做错太多该操作本质上不适合并行化,除非有一种有效的方法将初始字符串分解为正则表达式可以单独解析的几个较小的块(并行)。