为了完整起见,我在这里搜索并阅读了其他文章,例如:
Parallel.ForEach not spinning up new threads
但他们似乎没有解决我的情况,所以关闭我们去:
我有一个数组结构的Parallel.ForEach,如下所示:
Dim opts As New ParallelOptions
opts.MaxDegreeOfParallelism = intThreads
Parallel.ForEach(udtExecPlan, opts,
Sub(udtStep)
Dim strItem As String = udtStep.strItem
基本上,对于每个项目,我做一些嵌套循环,最后调用一个函数,将这些循环赋值作为参数 .
该函数执行一系列强烈的计算( which takes up most of the function's processing time )并将结果记录在MSSQL表中,如果满足某些条件,则函数返回True,否则返回False . 如果结果为True,那么我只是从并行函数Sub(udtStep)返回,并且数组中的另一个项应该继续 . 如果结果是False,我只是通过最深嵌套循环的另一个迭代,依此类推,努力完成其他外部循环等等 . 简而言之,所有嵌套循环都在主Parallel.ForEach中 . 循环,像这样:
Parallel.ForEach(udtExecPlan, opts,
Sub(udtStep)
Dim strItem As String = udtStep.strItem
If Backend.Exists(strItem) Then Return
For intA As Integer = 1 To 5
For intB As Integer = 1 To 50
Dim booResult As Boolean = DoCalcAndDBStuff(strItem, intA, intB)
If booResult = True Then Return
Next intB
Next intA
End Sub)
重要的是要注意udtExecPlan有大约585个元素 . 每个项目需要1分钟到几个小时才能完成 .
现在,问题出在这里:
我是否这样做:
Dim opts As New ParallelOptions
opts.MaxDegreeOfParallelism = intThreads
Parallel.ForEach(udtExecPlan, opts,
其中intThreads是核心数,或者我分配给它的任何数字(试过5,8,62,600),或者我是否只是省略了整个ParallelOptions声明并从Parallel.ForEach语句中选择,我注意到它会旋转我已经指定了多个线程,直到我的系统中的核心总数(包括HT核心) . 这一切都很好,很好 .
例如,在具有32核/ 64 HT内核和128GB RAM的HP DL580G7服务器上,我可以在任务管理器上看到5,8,62或64(使用600选项)线程忙,这是我所期望的 .
但是,当处理数组上的项目时,任务管理器上的线程“消失”(从大约75%的利用率变为0%)并且永远不会再次启动,直到只有1个线程正在工作 . 例如,如果我将intThreads设置为62(或者如果我省略整个ParallelOptions声明并且从Parallel.ForEach语句中选择,则无限制),我可以在db表上看到62(或64)个项目已被处理,但是从那时起在,它只是一次回落到1个线程和1个项目 .
我期待一个项目完成后新的线程会被旋转,因为有大约585个项目要经过 . 几乎就好像62或64个项目并行完成,然后只有1个项目直到完成,这使整个服务器几乎空转 .
我错过了什么?
我已尝试使用一个主要的Parallel.For循环(没有其他外部循环存在,就像在此示例中)并获得相同的行为 .
为什么?欢迎任何想法 .
我正在使用VS.NET 2015与.NET Framework 4.6.1,W2K8R2完全修补 .
谢谢!