使用C#和APM的CPU使用率不是100%的原因是什么?

问题描述 投票:13回答:3

我有一个CPU密集型的应用程序。在单个线程上处理数据时,CPU使用率会持续很长时间达到100%。因此应用程序的性能似乎受到CPU的约束。我已经多线程化了应用程序的逻辑,从而提高了整体性能。但是,CPU使用率几乎不超过30%-50%。我期望CPU(和许多核心)达到100%,因为我同时处理了许多数据集。

下面是我用来启动线程的逻辑的简化示例。当我运行这个例子时,CPU达到100%(在8/16核心机器上)。但是,我使用相同模式的应用程序没有。

public class DataExecutionContext
{
    public int Counter { get; set; }

    // Arrays of data
}

static void Main(string[] args)
{
    // Load data from the database into the context
    var contexts = new List<DataExecutionContext>(100);
    for (int i = 0; i < 100; i++)
    {
        contexts.Add(new DataExecutionContext());
    }

    // Data loaded. Start to process.
    var latch = new CountdownEvent(contexts.Count);
    var processData = new Action<DataExecutionContext>(c =>
    {
        // The thread doesn't access data from a DB, file, 
        // network, etc. It reads and write data in RAM only 
        // (in its context).
        for (int i = 0; i < 100000000; i++)
            c.Counter++;
    });

    foreach (var context in contexts)
    {
        processData.BeginInvoke(context, new AsyncCallback(ar =>
        {
            latch.Signal();
        }), null);
    }

    latch.Wait();
}

我已将锁的数量减少到严格的最小值(只有锁定器锁定)。我发现的最好方法是创建一个线程可以在内存中读/写的上下文。上下文不在其他线程之间共享。线程无法访问数据库,文件或网络。换句话说,我描述了我的应用程序,我没有发现任何瓶颈。

为什么我的应用程序的CPU使用率不会达到50%左右?这是我使用的模式吗?我应该创建自己的线程而不是使用.Net线程池吗?有没有陷阱?有什么工具可以推荐我找到我的问题吗?

谢谢!

c# .net multithreading asynchronous
3个回答
6
投票

有很多事情可能会导致这种行为。

首先,你有什么类型的CPU?如果您有i7或类似的处理器,操作系统会将其视为具有8个内核,而实际上,它有4个内核,具有2个超线程/核心。对于大多数操作而言,即使操作系统以这种方式看到,超线程也不能提供与第二个核心相同的可扩展性。我有这个原因导致我的整体CPU使用率低于操作系统......

其次,你可能会发生某种形式的真正共享。你提到你有锁定 - 即使它被保持在最低限度,锁可能会阻止你有效地安排这个。

此外,您现在正在安排所有100个工作项目。操作系统必须进出这100个线程。您可能希望将此限制为仅允许在给定时间处理特定数字。使用新的任务并行库(使用Parallel.ForEach并使用ParallelOptions设置来获得最大线程数)会更容易 - 但可以自己完成。

鉴于您要安排所有100个项目同时处理,分页可能会妨碍获得最大吞吐量的能力。

此外,如果您正在进行任何其他“更真实”的工作 - 您可能会遇到错误的共享问题,尤其是在您使用共享的数组或集合时(即使您处理的元素未共享)。

我建议在VS 2010中的并发分析器下运行它 - 它会让你更清楚地了解正在发生的事情。


2
投票

这是在没有看到您的应用程序的推测,但如果您的应用程序正在处理文件,数据库,创建大量对象(请求内存),使用网络设备或任何类型的硬件设备,那么这些因素可能会限制您的应用程序达到100%cpu使用率。这与线程切换相结合也可能是一个因素。

你说你使用的是你给出的示例模式,但是你说这个例子达到了100%的利用率但你的应用却没有。因此存在一些差异,您应该尝试更详细地描述您的应用程序正在做什么。 50%的利用率也不错。许多应用程序在超线程Intel CPU上运行率为50%,并且运行良好。如果应用程序没有达到100%的CPU利用率并且你仍然获得了良好的性能,那么我会说这实际上是一件好事,因为它意味着你有一些头部空间,因为它不再受CPU限制。这意味着其他事情可能占用CPU时间的情况下,您的应用程序不会受到太大影响。如果它处于100%利用率,那么当其他进程激活使用CPU时,您会看到应用程序性能动摇。


0
投票

如果要进行大量小内存分配 - 托管堆可以成为阻塞线程的共享资源,从而减慢进程并降低CPU使用率

© www.soinside.com 2019 - 2024. All rights reserved.