Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/268.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 多线程任务不使用CPU?_C#_.net - Fatal编程技术网

C# 多线程任务不使用CPU?

C# 多线程任务不使用CPU?,c#,.net,C#,.net,我在C#中有一个方法,我想在一台4核机器上,在控制台应用程序中从多个线程运行20次。我面临的问题是,结果并不是我所期望的那样。当我按顺序运行该方法25次时,所花费的时间是X,我可以在perfmon中看到最大CPU是100%(它告诉我它使用的是一个内核)。使用多个线程运行相同的方法,我希望执行时间为X/4,并且我还希望perfmon中的最大CPU使用率为400%(因为它是一台4核机器)。然而,我只能看到执行时间是X/2,最大CPU使用率从未超过275%。我尝试过各种方法,比如创建自己的线程、使用t

我在C#中有一个方法,我想在一台4核机器上,在控制台应用程序中从多个线程运行20次。我面临的问题是,结果并不是我所期望的那样。当我按顺序运行该方法25次时,所花费的时间是X,我可以在perfmon中看到最大CPU是100%(它告诉我它使用的是一个内核)。使用多个线程运行相同的方法,我希望执行时间为X/4,并且我还希望perfmon中的最大CPU使用率为400%(因为它是一台4核机器)。然而,我只能看到执行时间是X/2,最大CPU使用率从未超过275%。我尝试过各种方法,比如创建自己的线程、使用threasdpool等等,但似乎都不管用。谁能解释一下/帮我更好地理解它吗

另一件有趣的事情是,如果我使用
Thread.SpinWait(x)
将我的方法替换为一个虚拟任务,那么执行时间是x/4,我可以看到最大CPU将达到400%。这告诉我我的方法有问题,我不明白是什么。我的方法中没有锁/睡眠。以下是我用来执行的代码:

public static void DoWorkParallel()
{
    var s = new List<string> { "a", "b", "c", "d", "e", etc. };
    s.ParallelForEach2(x =>
                       {
                           MyTask(x);
                       });
}

public static void DoWorkSequential()
{
    var s = new List<string> { "a", "b", "c", "d", "e", etc. };
    foreach (var ss in s)
    {
        MyTask(x);
    }       
}

public static void ParallelForEach<T>(this IEnumerable<T> collection, Action<T> action)
{
    var results = collection.Skip(1).Select(item => new 
    {
        action,
        res = action.BeginInvoke(item, null, null)
    }).ToArray();

    action(collection.First()); /* let the mainthread do a job too*/

    foreach (var r in results)
    {
        r.action.EndInvoke(r.res); /*then wait the rest of time */
    }
}
publicstaticvoiddoworkparallel()
{
var s=新列表{“a”、“b”、“c”、“d”、“e”等};
s、 ParallelForEach2(x=>
{
我的任务(x);
});
}
公共静态void DoWorkSequential()
{
var s=新列表{“a”、“b”、“c”、“d”、“e”等};
foreach(s中的var ss)
{
我的任务(x);
}       
}
公共静态void ParallelForEach(此IEnumerable集合,操作)
{
var results=collection.Skip(1)。选择(项=>new
{
行动,
res=action.BeginInvoke(项,空,空)
}).ToArray();
操作(collection.First());/*让主线程也执行一项工作*/
foreach(结果中的var r)
{
r、 action.EndInvoke(r.res);/*然后等待剩余的时间*/
}
}
在一个紧密的循环中运行,不执行I/O,也不访问内存——它没有做任何有用的工作,因此将它的CPU使用率与任务的CPU使用率进行比较是一个谬误

如果没有任务正在执行的详细信息(是否访问文件、等待互斥体等),就很难确定发生了什么


您可以做的一件事是向任务中添加一个实例,并使用它打印每次调用所花费的时间。将运行任务的结果与
DoWorkSequential
ParallelForEach
进行比较——无论采用何种方法,每次调用都应花费相同的时间。如果ParallelForEach运行的任务花费的时间较长,则可能表明您有一个互斥锁,该互斥锁处于争用状态,需要用另一个锁定方法替换。

您可能需要在Parallel.Foreach调用的ParallelOptions参数中将MaxDegreeOfParallelism设置为4。如果不这样做,dotnet4会使用大量工作线程;它们的管理和同步开销可能有点浪费。我也有类似的问题,这对我来说很有效


此外,这里的事情要简单。请记住,当您使用紧密锻造的并行性时,您将每秒记录(cpu核心吞吐量)与每季度记录(程序员生产率)进行权衡

鉴于您未能提供
ParallelForEach2
的定义,这将是一个棘手的问题。对不起,我的错误。。请将其读为s.ParallelForEach(..MyTask()做什么?如果用SpinWait替换它,则CPU使用率将上升,这表明MyTask()不受(独占)CPU限制,需要访问共享资源,或者工作的执行速度快于虚拟任务中的等待时间。基本上是MyTask()去查找内存,进行一些计算,如果需要,分配更多内存。按顺序运行任务总是显示100%的CPU使用率,我认为这表明任务是CPU密集型的。据我所知,这些线程中使用的对象的任何实例之间都不共享内存。实际上是四个或两个内核具有超线程的内核?MyTask执行一些CPU密集型工作。它进入内存,查看一些缓存对象,并执行一些计算和创建更多内存等。查看perfmon表明没有I/O操作。线程也没有使用共享内存(同样,perfmon说没有冲突)。我将尝试添加秒表(),看看发生了什么。如果您在
MyTask
中的任何位置调用
new
(或者在调用
new
的类或容器上操作),随后的内存分配可能会触发垃圾回收。如果在任务期间连续创建并丢弃了许多对象,则GC成本可能会增加,并开始降低您的速度。