2

如何使用此代码使我的 i7 处理器达到 100% 的使用率?XmlDocument 中是否发生了一些特别的事情?仅仅是因为上下文变化吗?如果是这样,为什么放置更多线程不会使处理器使用其全部功能?一次解析多个字符串的最佳方法是什么?

编辑:

也许这段代码会让它更清楚,不管它使用 30% 的处理器的线程数是多少:

    private void Form1_Load(object sender, EventArgs e)
    {
        Action action = () =>
        {
            while (true)
            {
                XmlDocument xmlDocument = new XmlDocument();

                xmlDocument.LoadXml("<html><body><div>1111</div><div>222</div></body></html>");
                var nodes = xmlDocument.SelectNodes("//div");
            }
        };

        Parallel.For(0, 16, i => action());
    }
4

4 回答 4

3

这是您正在运行的实际代码,还是从文件或其他 URL 加载 xml?如果这是实际代码,那么它可能完成得太快,CLR 没有时间优化线程数,但是当你放置无限循环时,它保证你会最大化 CPU。

如果您从真实来源加载 XML,那么线程可以等待 IO 响应,并且在这种情况下不会消耗任何 CPU。为了加快这种情况,您可以使用大量线程(如 20+)将所有 XML 预加载到内存中,然后使用 8 个线程进行 XML 解析。

于 2012-05-02T20:58:41.573 回答
3

在您的代码示例中(您会通过探查器看到这一点),您正在浪费大量时间等待可用资源来运行这些线程。因为您不断地请求越来越多Parallel.For(这是一个非阻塞调用) - 您的进程花费大量时间等待线程完成,然后选择下一个线程(越来越多的此类线程都在请求运行时间)。

考虑分析器的输出:

红色是同步的!看看内核做了多少工作才能让我的应用程序运行这么多线程!注意,如果你有一个单核处理器,你肯定会看到 100%

在此处输入图像描述

通过拆分字符串并分别解析它们(当然是从 I/O 加载后),您将获得阅读此 xml 的最佳时间。您可能看不到 100% 的 CPU 使用率,但这将是最佳选择。使用字符串的不同分区大小(即子字符串大小)。

对于并行模式的惊人阅读,我推荐 Stephen Toub 的这篇论文:http: //download.microsoft.com/download/3/4/D/34D13993-2132-4E04-AE48-53D3150057BD/Patterns_of_Parallel_Programming_CSharp.pdf

编辑我做了一些寻找在多个线程中读取 xml 的智能方法。我最好的建议是:

  1. 如果可以,将您的 xml 文件拆分为较小的文件。
  2. 每个 xml 文件使用一个线程。
  3. 如果 1&2 不足以满足您的性能需求,请考虑不将其完全加载为 xml,而是对字符串进行分区(拆分),并手动解析(而不是 XmlDocument)。如果 1 和 2 足以满足您的需求,我只会这样做。每个分区(子字符串)都将在自己的线程上运行。还要记住“更多的线程”!=“更多的 cpu 使用率”,至少对于您的应用程序而言不是。正如我们在分析器示例中看到的,过多的线程会花费大量开销。把事情简单化。
于 2012-05-02T21:16:02.210 回答
0

处理器是现代 PC 上最快的组件。瓶颈通常以 RAM 或硬盘驱动器的形式出现。在第一种情况下,您不断地创建一个可能会占用大量内存的变量。因此,随着缓存快速耗尽,RAM 成为瓶颈是很直观的。

在第二种情况下,您没有创建任何变量(我确信 .NET 在后台做了很多工作,尽管是以高度优化的方式)。因此,所有工作都留在 CPU 上很直观。

操作系统如何处理内存、中断等是不可能完全定义的。您可以使用帮助定义这些情况的工具,但上次我检查时甚至没有用于 .NET 代码的内存分析器。所以这就是为什么我说对答案持保留态度。

于 2012-05-02T21:08:51.137 回答
0

任务并行库分发操作,因此您在进程利用率方面失去了一些控制。在大多数情况下这是一件好事,因为我们不必担心创建太多线程、使我们的线程太大等。如果您想显式创建线程,那么以下代码应该将您的处理器推到最大:

Parallel.For(0, 16, index => new Thread(() =>
                {
                    while (true)
                        new Thread(() =>
                            {
                                XmlDocument xmlDocument = new XmlDocument();
                                xmlDocument.LoadXml("<html><body><div>1111</div><div>222</div></body></html>");
                                var nodes = xmlDocument.SelectNodes("//div");
                            }).Start();
                }).Start());

我并不是说我推荐这种方法,只是展示了一个将我的处理器推到最大 (AMD FX-6200) 的代码的工作示例。我也看到大约 30% 的人使用任务并行库。

于 2013-03-25T03:59:45.003 回答